# Elasticsearchで複数インデックスをクエリする際に、インデックスが存在しなくても404エラーを出さないようにする

2021/05/29

アクセスログ分析などの目的で、日付でインデックスを切ってドキュメントを投入していること、あると思います。たとえば access-log-YYYY-MM-DD など。いくつかのインデックスの中からクエリしたいけど、それらのインデックスが存在しないこともある場合のクエリの書き方にちょっとハマったのでメモ。

# 基本は_search API叩く時にインデックスをカンマ区切りで列挙すれば事足りる

例えば、2021-05-28のインデックスと、2021-05-21のインデックスのみに対してクエリしたいとき、以下のような書き方がまず思いつくと思います。

POST /access-log-2021-05-21,access-log-2021-05-28/_search
{
    "query": {
        "bool": {
            "must": [
                { "terms": { "status": [500] } },
                { "terms": { "remote_ip": ["8.8.8.8", "1.1.1.1"] } }
            ]
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11

_searchAPIを叩くときのURLのインデックス名を、カンマ続きで複数書く方法です。

# 存在しないインデックスにクエリしようとするとエラーになる

この方法、複数書いたインデックスが全て存在するならいいのですが、全てのインデックスが存在しないと使えません。

どれか一つのインデックスでも存在しないと、HTTP 404で返ってきてしまい、index_not_found_exceptionno such index [access-log-2021-05-28]と言われてしまいます。

# 解決法: queryオブジェクトにインデックス名を指定しよう

URLには検索対象のインデックスをワイルドカードで指定しておき、queryオブジェクトの中で_index条件を付ければOK。

POST /access-log-*/_search
{
    "query": {
        "bool": {
            "must": [
                { "terms": { "status": [500] } },
                { "terms": { "remote_ip": ["8.8.8.8", "1.1.1.1"] } },
                { "terms": { "_index": ["access-log-2021-05-21", "access-log-2021-05-28"] } },
            ]
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

これだと、存在しないインデックスがあっても、きちんとHTTP 200で返ってきます。

# パフォーマンスについても心配ない

ワイルドカードつけてaccess-log-*に当てはまる全てのインデックス検索しちゃわない? めっちゃ遅くなるんじゃないの? と思うかもしれませんが、ElasticSearchくん賢いので大丈夫です。

クエリがどういう検索をするか(SQLにおけるEXPLAINみたいな)は、KibanaのDev Tools => Search Profilerにかけると見ることができます。

そもそも指定した2つのインデックスしか検索対象になっていないので大丈夫です。

おわり。

コメント

コメントする

name
content