Elasticsearch 7.2.1 で join datatype を使って親子関係を実現した際に、子データが無い親を検索する
6884 ワード
Elasticsearch で親子関係のデータをインデクシングした際に、子データが無い親のデータを検索したい時があります。
手元の環境は以下になります。
- Ubuntu 18.04 LTS
- Elasticsearch 7.2.1
最初にインデックスの設定とマッピングを定義します。( こちらの記事と同じものです。)
次に、以下のようなデータで json ファイルを作成します。
{"index": {"_index": "shop", "_type": "_doc","_id": "goods_id.1"}}
{"type": "goods","name": "三岳","text": "もののけ姫のモデルにもなった、鹿児島県屋久島の焼酎です。屋久島は水が美味しく、その水を使って作られています。ロックで飲むことをオススメします。","my_join_field": "goods"}
{"index": {"_index": "shop", "_type": "_doc","_id": "review_id.1", "routing": "goods_id.1"}}
{"type": "review","user": "nettle0010","text": "何度も購入させていただいてます。以前はレア物でなかなか飲めませんでしたが、こちらで購入できるようになって晩酌で楽しんでます。","my_join_field": {"name": "review", "parent": "goods_id.1"}}
{"index": {"_index": "shop", "_type": "_doc","_id": "review_id.2", "routing": "goods_id.1"}}
{"type": "review","user": "udfhsudadb","text": "注文してから2〜3日で届きました。ありがとうございます!","my_join_field": {"name": "review", "parent": "goods_id.1"}}
{"index": {"_index": "shop", "_type": "_doc","_id": "goods_id.2"}}
{"type": "goods","name": "屋久の島","text": "もののけ姫のモデルにもなった、鹿児島県屋久島の焼酎です。三岳と違ってあまりメジャーではありませんが、なかなか美味しいです。ロックがオススメです。","my_join_field": "goods"}
{"index": {"_index": "shop", "_type": "_doc","_id": "review_id.3", "routing": "goods_id.2"}}
{"type": "review","user": "okodshywegfej","text": "昨年購入しました。両親からも喜ばれています。","my_join_field": {"name": "review", "parent": "goods_id.2"}}
{"index": {"_index": "shop", "_type": "_doc","_id": "goods_id.3"}}
{"type": "goods","name": "原酒三岳","text": "もののけ姫のモデルにもなった、鹿児島県屋久島の焼酎です。三岳の原酒です。ロックがオススメです。","my_join_field": "goods"}
そして、json ファイルを使ってインデクシングします。
$ curl -H "Content-type: application/x-ndjson" -X POST http://localhost:9200/_bulk?refresh=false --data-binary @request_bulk.json | jq
$ curl -X POST 'localhost:9200/shop/_refresh' | jq
子データが2つのもの、1つのもの、ひとつも無いもの、の3つの親データを作成しています。
子データが無い親を検索してみます。
$ curl -X POST 'localhost:9200/shop/_search' -H 'Content-Type: application/json' -d'
{
"from": 0,
"size": 10,
"query": {
"bool": {
"filter": [
{ "term": { "type": "goods" } }
],
"must_not": {
"has_child": {
"type": "review",
"query": {
"match_all": {}
}
}
}
}
}
}
' | jq
以下のような結果が返ってきます。
{
"took": 0,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0,
"hits": [
{
"_index": "shop",
"_type": "_doc",
"_id": "goods_id.3",
"_score": 0,
"_source": {
"type": "goods",
"name": "原酒三岳",
"text": "もののけ姫のモデルにもなった、鹿児島県屋久島の焼酎です。三岳の原酒です。ロックがオススメです。",
"my_join_field": "goods"
}
}
]
}
}
ポイントは以下になります。
- must_not に全件取得の has_child を指定する。
なお、以下のようなクエリを実行すると0件も含めた親ごとの子データの数を取得できます。
$ curl -X POST 'localhost:9200/shop/_search' -H 'Content-Type: application/json' -d'
{
"from": 0,
"size": 10,
"query": {
"bool": {
"should": [
{
"has_child": {
"type": "review",
"score_mode": "sum",
"query": {
"match_all": {}
}
}
},
{
"bool": {
"filter": [
{ "term": { "type": "goods" } }
],
"must_not": {
"has_child": {
"type": "review",
"score_mode": "sum",
"query": {
"match_all": {}
}
}
}
}
}
]
}
}
}
' | jq
以下のような結果が返ってきます。
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 3,
"relation": "eq"
},
"max_score": 2,
"hits": [
{
"_index": "shop",
"_type": "_doc",
"_id": "goods_id.1",
"_score": 2,
"_source": {
"type": "goods",
"name": "三岳",
"text": "もののけ姫のモデルにもなった、鹿児島県屋久島の焼酎です。屋久島は水が美味しく、その水を使って作られています。ロックで飲むことをオススメします。",
"my_join_field": "goods"
}
},
{
"_index": "shop",
"_type": "_doc",
"_id": "goods_id.2",
"_score": 1,
"_source": {
"type": "goods",
"name": "屋久の島",
"text": "もののけ姫のモデルにもなった、鹿児島県屋久島の焼酎です。三岳と違ってあまりメジャーではありませんが、なかなか美味しいです。ロックがオススメです。",
"my_join_field": "goods"
}
},
{
"_index": "shop",
"_type": "_doc",
"_id": "goods_id.3",
"_score": 0,
"_source": {
"type": "goods",
"name": "原酒三岳",
"text": "もののけ姫のモデルにもなった、鹿児島県屋久島の焼酎です。三岳の原酒です。ロックがオススメです。",
"my_join_field": "goods"
}
}
]
}
}
ポイントは以下になります。
- score_mode に sum を指定する。(全件取得のクエリなので、それぞれの子データのスコアが 1 になり、sum を指定することで結果的に子データの数になる)
参考になった記事
Has child query
Elasticsearch get all parents with no children
How to sort parents by number of children in Elasticsearch
Author And Source
この問題について(Elasticsearch 7.2.1 で join datatype を使って親子関係を実現した際に、子データが無い親を検索する), 我々は、より多くの情報をここで見つけました https://qiita.com/nettle0010/items/9d4b68d15e1b22073470著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .