目次
久しぶりに翻訳ではないブログを。書こうと思いながらかけてなかったので。。。
今回はvalidate APIの紹介です。
背景
ElasticsearchのクエリはQuery DSLというJSONで クエリを定義できるものを提供しています。 これは、様々なクエリ、フィルタを定義するために必要です。
自分の望んでいる条件を記述するために、JSONのネストと格闘することも必要となります。。。 また、クエリ、フィルタには様々なパラメータが用意されています。 これらのパラメータをすべて覚えるのは無理でしょうし、タイプミスなどもありますよね。 タイプミスやカッコのミスマッチなどで格闘して1時間が経過してしまったなどもあると思います。
そんな時に便利なAPIとして用意されているのがvalidate APIです。
利用方法
APIが用意されています。
http://ホスト名:ポート番号/インデックス名/タイプ名/_validate/query
インデックス名
やタイプ名
は省略可能ですが、マッピングが異なると思うので、タイプ名まで指定するほうが良いと思います。
上記のAPIに対してクエリを送信するだけです。
クエリの確認
たとえば、こちらのGistにあるようなマッピングのインデックスに対して
検索クエリを組み立てていて、エラーが出るとします。
※このクエリはmatch_all
のところをmatch_al
と、l
が1文字足りないクエリになっています。
検索クエリのリクエスト(エラーあり)
GET pref_aggs/_search
{
"query": {
"match_al": {}
}
}
実行結果のレスポンス
{
"error": "SearchPhaseExecutionException[Failed to execute phase [query], all shards failed; shardFailures {[rwkb01chTZq2V7FD0Tlwrw][pref_aggs][0]: SearchParseException[[pref_aggs][0]: from[-1],size[-1]: Parse Failure [Failed to parse source [{\n \"query\": {\n \"match_al\": { }\n }\n}\n]]]; nested: QueryParsingException[[pref_aggs] No query registered for [match_al]]; }{[rwkb01chTZq2V7FD0Tlwrw][pref_aggs][1]: SearchParseException[[pref_aggs][1]: from[-1],size[-1]: Parse Failure [Failed to parse source [{\n \"query\": {\n \"match_al\": { }\n }\n}\n]]]; nested: QueryParsingException[[pref_aggs] No query registered for [match_al]]; }]",
"status": 400
}
とこんなかんじで、エラーが帰っては来るのですが、非常に読みづらいです。
そこで、validate API
を利用します。
リクエスト先を/_search
から/_validate/query
に変更します。
validate API
GET pref_aggs/_validate/query
{
"query": {
"match_al": {}
}
}
validate APIのレスポンス
{
"valid": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
}
}
すると、非常にシンプルな結果が返ってきます。
"valid": false
となっているため、クエリに問題があることがわかります。
エラーの詳細
問題がある事自体はわかりましたが、エラーの内容も知りたいですよね?
その場合は、explain
というパラメータを追加します。
(正しくはexplain=true
を追加しますが、=true
を省略可能です。)
validate API(explainあり、クエリ自体は省略)
GET pref_aggs/_validate/query?explain
{...}
validate APIのレスポンス
{
"valid": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"explanations": [
{
"index": "pref_aggs",
"valid": false,
"error": "org.elasticsearch.index.query.QueryParsingException: [pref_aggs] No query registered for [match_al]"
}
]
}
explanations
という項目が追加されました。
ここにerror
という項目として、エラーの詳細が返ってきます。_search
の時よりも見やすいですね。
今回のエラーは、match_all
が正しいクエリですの、match_al
というクエリは登録されていないというエラーでした。
では、クエリを修正して実行しましょう。
validate API(エラー無し)
GET pref_aggs/_validate/query?explain
{
"query": {
"match_all": {}
}
}
validate APIのレスポンス
{
"valid": true,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"explanations": [
{
"index": "pref_aggs",
"valid": true,
"explanation": "ConstantScore(*:*)"
}
]
}
今度はクエリに問題はありません。"valid": true
です。
そして、explanations
の項目には、error
の代わりにexplanation
という項目が返ってきました。
これが、実際にElasticsearch内部で実行されるクエリになります。
実際のクエリに利用される単語の確認
この機能はこの他に、クエリの解析にも利用できます。 思ったとおりに検索にヒットしない場合があって、困ったことはないですか? フィールドに指定されたアナライザによっては、単語を変形したりするものが存在します。
サンプルマッピング
PUT /validate_sample
{
"mappings": {
"several_analyzer": {
"properties": {
"title": {"type": "string"},
"body_ja": {"type": "string", "analyzer": "kuromoji"},
"body_en": {"type": "string", "analyzer": "english"}
}
}
}
}
例えば、このようにkuromoji
、english
、デフォルト(standard
)アナライザを利用したマッピングがあるとします。
このフィールドに対してpowerful
という単語で検索したとします。
validate API
GET /validate_sample/_validate/query?explain
{
"query": {
"multi_match": {
"fields": ["body_en","body_ja","title"],
"query": "powerful"
}
}
}
この場合、レスポンスは次のとおりです。
validate APIのレスポンス
{
"valid": true,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"explanations": [
{
"index": "validate_sample",
"valid": true,
"explanation": "(title:powerful | body_en:power | body_ja:powerful)"
}
]
}
title
、body_ja
については入力された単語がそのままクエリとして利用されています。
body_en
については、power
という単語に変換されて実行されています。
これは、english
アナライザがステミングを行った結果がクエリとして利用されるという意味です。
また、powerful
を秋葉原
といった日本語に変更して実行すると次のようになります。
日本語はstandard
アナライザなどでは、1文字ずつ区切られてしまうことがわかります。
validate APIのレスポンス
{
"valid": true,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"explanations": [
{
"index": "validate_sample",
"valid": true,
"explanation": "((title:秋 title:葉 title:原) | (body_en:秋 body_en:葉 body_en:原) | ((body_ja:秋葉 body_ja:秋葉原) body_ja:原))"
}
]
}
このように、クエリの単語がどのような単語に変換されてクエリに利用されているかなども知ることが可能です。
また、クエリを組み立てて、ヒットするはずが、0件となってしまうという場合にも、どのようなクエリが組み立てられているかを確認するという点で、
validate API
が役立ちます。
検索がヒットするが、望んだクエリになっていないのでは?という場合は_search API
のexplain
パラメータを
利用すれば、クエリの構成がわかるのですが、検索結果が0件の場合はクエリの構成は表示されません。
解決できない問題は?
便利なvalidate APIですが、以下の問題に対しては残念ながら確認できません。
query
以外の項目のvalidate不可- たとえば、
_search API
のsize
などの項目についてはチェックできないです。
- たとえば、
- 存在しないフィールドの指定
- 上記
validate_sample
のマッピングの例でクエリにbody_eng
という存在しないフィールドを指定してもエラーとはなりません。
- 上記
まとめ
書いたクエリがうまく動かない、JSONのタグがおかしいといった場合は、
まずはこのvalidate API
で確認してみるのがオススメです。
comments powered by Disqus
See Also by Hugo
- elasticsearch-inquisitorプラグインの紹介
- Querqyの調査(その2:アーキテクチャ)
- Querqyの調査(その1)
- Elasticsearchの新しいJavaクライアント
- Azure Cognitive Searchでオートコンプリートやサジェストをしてみる