ポイント: ElasticSearchはネストされたJSONドキュメントで苦労することがあり、誤った検索結果を引き起こす可能性があります。これに対処するために、ネストされた構造を認識するためにインデックスを明示的に定義し、埋め込まれたドキュメントのクエリ時に検索精度を向上させます。
- ネストされたJSONオブジェクトはElasticSearchでの検索結果を複雑にする可能性があります。
- 埋め込まれたドキュメントの正確なクエリには、明示的なインデックス作成が必要です。
ElasticSearchは時々非常に複雑です。検索を実行すると誤った結果が返され、それに気づかないことがあります。これは、たとえば、ネストされたJSONドキュメントがあるときに発生する可能性があります。つまり、1つのJSONドキュメントの中に別のJSONドキュメントがある場合です。これは、Lucene(つまり、ElasticSearch)のクエリがJSONドキュメント内のオブジェクト階層を理解していないためです。
ネストされたJSONオブジェクトの検索に関する問題
問題と解決策を示すために、このプログラムmassAdd.pyをダウンロードし、URLを自分のElasticSearch環境に合わせて変更します。それを実行してください。その後、読み込まれたデータを確認します。ブラケットから、classesがJSON配列であることがわかります。しかし、インデックスは、見ての通り、これを反映していません。
curl -XGET --header 'Content-Type: application/json' http://parisx:9200/universities/_search?pretty}
"_index" : "universities",
"_type" : "universities",
"_id" : "428b71b0b935eaf58bdf874c819f263a919da5f3",
"_score" : 0.0,
"_source" : {
"firstName" : "Stephen",
"classes" : [
{
"name" : "French",
"grades" : 2
},
{
"name" : "French",
"grades" : 3
},
{
"name" : "French",
"grades" : 2
},
{
"name" : "physics",
"grades" : 6
},
{
"name" : "physics",
"grades" : 5
}
],
"lastName" : "Shakespeare",
"school" : "Arizona State University"
}
}
]
}
インデックスマッピングがJSON配列を示していないことに注意してください。これは、ブラケット[]がないからではありません。むしろnestedという単語が欠けています。
curl -XGET --header 'Content-Type: application/json' http://parisx:9200/universities?pretty
...
"classes" : {
"properties" : {
"grades" : {
"type" : "long"
},
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
...
物理学を受講している学生を検索するために論理的だと思われる方法を使用して検索を実行してください:
curl -XGET --header 'Content-Type: application/json' http://parisx:9200/universities/_search/?pretty=true -d '{
"query": {
"bool" : {
"must" : [
{ "match" : {"classes.name" : "physics"} },
{ "match" : {"classes.grades" : 1} }
]
}
}
}'
この誤った結果が生成されます。これは、Luceneがドキュメント全体をフラット化し、両方のclasses.grades 1とclasses.name physicsを見つけるためです。
{
"_index" : "universities",
"_type" : "universities",
"_id" : "5846c01f90d80448ab087bf4f476cd3f8ab6f683",
"_score" : 1.621972,
"_source" : {
"classes" : [
{
"grades" : 2,
"name" : "physics"
},
{
"grades" : 2,
"name" : "French"
},
{
"grades" : 3,
"name" : "physics"
},
{
"grades" : 1,
"name" : "math"
}
],
"firstName" : "Stephen",
"lastName" : "Rowe",
"school" : "University of South Carolina - Columbia"
}
}
インデックスを明示的にする
データを読み込むだけでElasticSearchにインデックスを作成できます。それが即座に作成されます。しかし、そうするとインデックスの作成方法を制御することはできません。したがって、インデックス作成を明示的にして、classesがJSON配列であることを明確にします。最初にインデックスを削除します。これにより、すべてのデータも削除されます。
curl -XDELETE http://parisx:9200/universities
次に、新しいインデックスを作成し、classesが大学オブジェクト内のオブジェクトであることを明示的に示します。"type":"nested"を使用します。注意: 大学データは入力していません。学生だけです。そのため、これらのフィールドは無視してください。(大学データは別の投稿で使用し、前の投稿で使用しました)。
curl -XPUT --header 'Content-Type: application/json' http://parisx:9200/universities -d '{
"mappings" : {
"universities" : {
"properties" : {
"Address" : { "type" : "text"},
"AdminEmail" : { "type" : "text"},
"AdminName" : { "type" : "text" },
"AdminPhone" : { "type" : "text" },
"DapipId" : { "type" : "text" },
"Fax" : { "type" : "text" },
"GeneralPhone" : { "type" : "text" },
"LocationName" : { "type" : "text" },
"LocationType" : { "type" : "text" },
"OpeId" : { "type" : "text" },
"ParentDapipId" : { "type" : "text" },
"ParentName" : { "type" : "text" },
"UpdateDate" : { "type" : "text" },
"classes" : {
"type" : "nested",
"properties" : {
"name" : { "type" : "text"},
"grades" : { "type" : "integer" }
}
},
"firstName" : { "type" : "text" },
"lastName" : { "type" : "text" },
"school" : { "type" : "text" }
}
}
}
}'
次に、massAdd.pyを再度実行してデータを再度読み込みます。今度は、物理学で1の成績を取得した学生を見つけるために、クエリにnestedとpathの用語を追加します。pathは、JSON内の親オブジェクトであり、この場合はclassesです。そして、クラス名で検索するためにclasses.nameを使用します:
curl -XGET --header 'Content-Type: application/json' http://parisx:9200/universities/_search/?pretty=true -d '{
"query": {
"nested" : {
"path" : "classes",
"score_mode" : "avg",
"query" : {
"bool" : {
"must" : [
{ "match" : {"classes.name" : "physics"} },
{ "match" : {"classes.grades" : 1} }
]
}
}
}
}
}'
正しい結果が得られます。
{
"_index" : "universities",
"_type" : "universities",
"_id" : "20ce682e16d0b88487addc9ceba2a695d57692aa",
"_score" : 2.188588,
"_source" : {
"lastName" : "Shakespeare",
"firstName" : "Julie",
"classes" : [
{
"grades" : 1,
"name" : "physics"
},
{
"grades" : 6,
"name" : "math"
}
],
"school" : "Arizona State University"
}
}
]
ElasticSearchガイド
- 初心者のためのElasticSearchチュートリアル: ElasticSearchの基本
- ElasticSearchでApache Hiveを使用する
- ElasticSearchをApache Sparkで使用する
- Curl ElasticSearchコマンドチートシート
- Spark ElasticSearch Hadoopの更新とUpsertの例と説明
- Pythonを使用してApache SparkデータをElasticSearchに書き込む方法
- ElasticSearch検索構文とブールおよび集約検索
- ElasticSearchネストされたクエリ: 埋め込まれたドキュメントの検索方法
- ElasticSearch結合: Has_Child、Has_parentクエリ
- Elasticバージョン7クラスターの設定方法
- nginxとElasticSearchのためのFilebeatの設定方法
- BeatsとLogstashを使用してElasticSearchにログを送信する
- Logstashを使用してCSVファイルをElasticSearchに読み込む方法
- ElasticSearch集約の説明
- ELKスタックとは何ですか?
- Logstash 101: データ処理パイプラインでのLogstashの使用
- Kibanaを使用してElasticSearchでLuceneとKibanaクエリ言語を使用してクエリを実行する
- ElasticSearch機械学習
- Elastic Enterprise Searchのインストール方法
- GitHubでElastic Enterprise Searchを使用する方法
これらの投稿は私自身のものであり、必ずしもBMCの立場、戦略、または意見を代表するものではありません。