こんにちは。WEBサービス開発グループの中野です。
前回の ElasticsearchのField Collapsingで検索結果をグルーピングする に引き続き、Elasticsearch の便利な機能を試してみたいと思います。
今回は「ドキュメントにマッチする検索条件を探す」という一風変わった機能の Percolator(パーコレータ) を利用してみます。
特に、Elasticsearch 5系から利用方法が変わっていますので、注意して確認したいと思います。
概要
通常の検索は「検索条件にマッチするドキュメントを探す」というアプローチですが、Percolatorはその逆で「ドキュメントにマッチする検索条件を探す」ことができる機能になります。
ちょっとイメージしづらいですが、下図のように考えると分かりやすいかもしれません。
使い方
ドキュメント に従って Percolator の使い方を確認したいと思います。
具体例として、@nifty不動産 のような物件情報検索サービスでユーザの検索条件ごとに新着物件を判定するユースケースを考えてみます。
先ほどのイメージ図に当てはめると、下図のようになります。
インデックスの作成
まずは、検索条件を登録するためのインデックスを作成します。
下記のクエリでは my-percolator というインデックスを作成し、検索条件を入れる percolator型 の query フィールドと、検索条件の中で利用する station フィールドと rent フィールド(型は任意)を定義しています。
5系のドキュメント では2つのtype(mapping)を定義していますが、6系のドキュメント にあるように1つのtypeにした方がよいと思います(理由は後述します)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
PUT /my-percolator { "mappings": { "my-percolator": { "properties": { "query": { "type": "percolator" }, "station": { "type": "keyword" }, "rent": { "type": "integer" } } } } } |
検索条件の登録
次に、先ほど作成したインデックスに検索条件を登録していきます。
下記のクエリでは、
Aさんの検索条件として station が 新宿 かつ rent が 80,000 以下、
Bさんの検索条件として station が 池袋 かつ rent が 90,000 以下、
Cさんの検索条件として station が 池袋 かつ rent が 75,000 以下、
という3つの検索条件を登録しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
PUT /my-percolator/my-percolator/A?refresh { "query": { "bool": { "filter": [ { "term": { "station": "新宿" } }, { "range": { "rent": { "lte": 80000 } } } ] } } } PUT /my-percolator/my-percolator/B?refresh { "query": { "bool": { "filter": [ { "term": { "station": "池袋" } }, { "range": { "rent": { "lte": 90000 } } } ] } } } PUT /my-percolator/my-percolator/C?refresh { "query": { "bool": { "filter": [ { "term": { "station": "池袋" } }, { "range": { "rent": { "lte": 75000 } } } ] } } } |
my-percolator をそのまま検索してみると、指定したとおりの検索条件が登録されていることが確認できます。
1 2 3 4 5 6 |
GET my-percolator/_search { "query": { "match_all": {} } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
{ "took": 1, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 3, "max_score": 1, "hits": [ { "_index": "my-percolator", "_type": "my-percolator", "_id": "A", "_score": 1, "_source": { "query": { "bool": { "filter": [ { "term": { "station": "新宿" } }, { "range": { "rent": { "lte": 80000 } } } ] } } } }, { "_index": "my-percolator", "_type": "my-percolator", "_id": "C", "_score": 1, "_source": { "query": { "bool": { "filter": [ { "term": { "station": "池袋" } }, { "range": { "rent": { "lte": 75000 } } } ] } } } }, { "_index": "my-percolator", "_type": "my-percolator", "_id": "B", "_score": 1, "_source": { "query": { "bool": { "filter": [ { "term": { "station": "池袋" } }, { "range": { "rent": { "lte": 90000 } } } ] } } } } ] } } |
Percolatorの実行
検索条件の準備ができましたので、いよいよ Percolator を実行してみましょう。
Percolator の実行には percolate 句を指定します。
上記で登録した3つの検索条件に対して、新着物件が追加されたという想定で station が 池袋 rent が 85,000 というドキュメントをあててみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
GET /my-percolator/_search { "query": { "percolate": { "field": "query", "document_type": "rent-percolator", "document": { "station": "池袋", "rent": 85000 } } } } |
すると、先ほど登録したBの検索条件がヒットしましたので、今回追加された新着物件はBさんの検索条件にマッチしている、ということが分かります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
{ "took": 14, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 1, "max_score": 0, "hits": [ { "_index": "my-percolator", "_type": "my-percolator", "_id": "B", "_score": 0, "_source": { "query": { "bool": { "filter": [ { "term": { "station": "池袋" } }, { "range": { "rent": { "lte": 90000 } } } ] } } } } ] } } |
Percolator の基本的な使い方については、以上となります。
注意事項
APIの仕様変更
Percolator は5系以前(~2.4)では Percolator API として提供されていましたが、現行の5系からは Percolator API は非推奨となり、代わりに Percolate Query として提供されています。
これから新たに Percolator を利用する場合には、Percolate Query を利用するようにしましょう。
typeの廃止(予定)
今後のバージョンアップで typeの廃止 が予定されています。
Percolator についても、5系のドキュメント では一つのインデックスに複数のタイプを作成する記述がありますが、次期バージョンの 6系のドキュメント では一つのインデックスに一つのタイプ定義となっていますので、将来のタイプ廃止に備えて一つのインデックスに一つのタイプとなるように定義しましょう。
Elasticsearch は特にバージョンアップのスピードが早く今後もAPIの仕様やクエリの記述方法が変更される可能性があると思いますので、公式ブログ のリリース情報などを参考に、非推奨や廃止となる可能性のある機能を避けるようにして利用していきたいですね。
まとめ
Percolator はいかがでしたでしょうか。
WEBサイトやECサービスでコンテンツの更新時にユーザごとに新着情報をお知らせしたり、あらかじめ定義しておいたルールにそってコンテンツを分類したりする用途に利用できそうですね。
ニフティのWEBサービスでも Percolator などの便利な機能を活用していきたいです。
おまけ
最近 Elasticsearchのグッズを販売する オンラインショップがオープンされました。
ロゴやイラストの入ったTシャツや折りたたみ傘などが販売されていますので、興味のある方は覗いてみてはいかがでしょうか。
私も個人的にTシャツを購入してみましたが、Elasticの名のとおり? 着ごごちがよかったです。