目次
今年初の「突撃!隣のElasticsearch」ということで、Wantedlyさんにおじゃましました。
※写真を自分でも撮ったのですが、画像が壊れてたので、一緒に行ったペンギン先生の写真を拝借しました。
第3回のElasticsearch勉強会を開催中にES使ってるってツイートを見つけたので、アタックかけて遊びに行きました。 交渉に快諾いただきありがとうございました!
WantedlyさんがどのようにElasticsearchを使用されているかはきっと、ブログを書いてくれると思うので期待しておくとして、書いてくれました!! 「実践!Elasticsearch」
そこで、nested
でハイライトがなんかうまくいかないって話があったので、ちょっと調べてみました。
(※まだ、調査中です)
前提条件
再現する手順はgistにあります。(Senseに貼り付ければ動作します。ただし、elasticsearch-analysis-kuromojiが必要です。)https://gist.github.com/johtani/9184287
なお、このマッピングやデータはWantedlyさんとは全く関係ありません。
nested
フィールド内部のデータに対して、検索しハイライトしようとするとうまく動作しないという状況です。
マッピングは以下のとおり。
"books" : {
"properties": {
"book" : {
"type": "nested",
"properties": {
"title" : { "type": "string", "analyzer": "kuromoji", "store": "no"},
"contents" : {"type": "string", "analyzer": "kuromoji", "store": "yes"}
}
}
}
}
}
このマッピングの特徴は以下のとおり。
_source
は保存される(デフォルト値)book
がnested
なオブジェクトtitle
はstore : no
contents
はstore : yes
動作の挙動をわかりやすくするため、title
とcontents
のstore
属性に違いを持たせてあります。
問題点
nested
クエリを使って、検索した時にハイライトが返ってきません。
次のクエリを実行するとわかります。
GET /bookstore/books/_search
{
"_source" : ["book.title","book.contents"],
"fields": [
"book.title",
"book.contents"
],
"query": {
"nested": {
"path": "book",
"query": {
"query_string" : {
"query" : "Solr",
"fields" : ["book.title", "book.contents"]
}
}
}
},
"highlight": {
"pre_tags": ["<b>"],
"post_tags": ["</b>"],
"fields": {
"*": {}
}
}
}
結果はこちら。 ハイライトがありません。
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.5,
"hits": [
{
"_index": "bookstore",
"_type": "books",
"_id": "1",
"_score": 0.5,
"_source": {
"book": {
"title": "Apache Solr入門",
"contents": "Apache Solrについて日本語で書かれた唯一の書籍です。SolrはLuceneをコアにした検索サーバです。"
}
}
}
]
}
}
次に、ハイライトが帰ってくるパターン。
nested
クエリではなく、_all
を対象としたクエリを投げます。
{
"_source" : ["book.title","book.contents"],
"fields": [
"book.title",
"book.contents"
],
"query": {
"query_string" : {
"query" : "Solr",
"fields": [
"_all"
]
}
},
"highlight": {
"pre_tags": ["<b>"],
"post_tags": ["</b>"],
"fields": {
"book.title" : {},
"book.contents": {}
}
}
}
この場合の結果は次の通り。
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.27063292,
"hits": [
{
"_index": "bookstore",
"_type": "books",
"_id": "1",
"_score": 0.27063292,
"_source": {
"book": {
"title": "Apache Solr入門",
"contents": "Apache Solrについて日本語で書かれた唯一の書籍です。SolrはLuceneをコアにした検索サーバです。"
}
},
"highlight": {
"book.title": [
"Apache <b>Solr</b>入門"
]
}
}
]
}
}
ハイライトが返ってきています。
考察(原因は未特定)
残念ながら、まだ調査してません。 まずは、現象が理解できたというだけです。 問題点が実は2つありそうです。
問題点1:nested
クエリの場合に、ハイライトされない。
nested
クエリではハイライトが動作していないようです。
想像ですが、検索に利用されたクエリで指定されているフィールドをハイライタ(ハイライトを実行するモジュール)が認識できてないのではないかと。
なぜ認識できていないのかという点を調査する必要がありそうです。
考察(試してみたパターン)
nested
ではないクエリで、ハイライトが動作しているのですが、 "book.title" : {"require_field_match" : true},
にした場合は、ハイライトが返ってこないです。
このオプションは、検索対象のフィールドでマッチした文字列だけがハイライトされるオプションになります。
したがって、book.title
フィールドに対する検索でSolr
という文字を検索していないことになります。
_all
に対するクエリであるためです。
このため、例えば、title
だけを検索対象にしたのに、contents
にSolr
という文字が入っていてもハイライトされてしまうという状況が発生します。
問題点2 store : yes
のデータがハイライトできない。
GithubにIssueをあげました。https://github.com/elasticsearch/elasticsearch/issues/5245 (2014/02/25追記)
nested
オブジェクトにあるデータのうち、store : no
のものだけがハイライト結果として返ってきました。
考察
なぜ、store : yes
のデータがハイライトされないかを調べるために、fields
パラメータをリクエストに追加してみました。
{
"_source" : ["book.title","book.contents"],
"fields": [
"book.title",
"book.contents"
],
...
}
すると、fields
の戻り値は次のとおりです。
...
"fields": {
"book.title": [
"Apache Solr入門"
]
},
...
このことから、store : no
のデータの場合、_source
から値を取得して返却しているというのがわかります。
ハイライトがされない原因も、fields
で値が取れていないのも同じ原因であると思われます。
なぜなら、ハイライトは、保存された文字列を内部で取り出し利用して、ハイライトタグを埋め込むという動作をするためです。
参考?
これらの問題点についてですが、次のIssueが関係あるかもしれません。
Return matching nested inner objects per hit #3022
今後?
残念ながら、現時点では、問題点がどんなものかというのを理解しただけとなります。 デバッグしたりソースを追っかけたりして何が問題なのかを調べて行ってみようかなぁと。
なにか、気づいたことなどあればコメントしてもらえると助かります。
comments powered by Disqus
See Also by Hugo
- Elasticsearchの新しいJavaクライアント(2024年3月版)
- Elasticsearchの新しいJavaクライアント
- ローマ字入力のゆれと読み(JapaneseCompletionAnalyzerその2)
- OData式と日本語の検索(NGram)とフレーズ検索
- Index Template V2