Elasticsearch中的嵌套查詢介紹及實例

大家在工作中想必也接觸過Elasticsearch,今天介紹一下es中的嵌套對象及對應的查詢方式。

 

從考慮一個業務場景開始吧,業務上需要把某些類似的商品聚合成爲一個關聯組,需要支持根據某個商品的特徵,查詢到它所在的關聯組,es中的存儲結構如下:

{
    "memberGoods":[
        {
            "title":"商品A",
            "brand":"a"
        },
        {
            "title":"商品B",
            "brand":"b"
        }
    ],
    "groupId":"A"
}

那麼問題來了,如果memberGoods是一個普通的Object類型,對於下面的查詢條件:

{
    "query":{
        "bool":{
            "must":[
                {
                    "match":{
                        "title":"商品A"
                    }
                },
                {
                    "match":{
                        "brand":"b"
                    }
                }
            ]
        }
    }
}

上面的數據依然會匹配上,但是商品A的品牌應該是a,而不是b呀,造成這種現象的原因是結構性的JSON文檔會平整成索引內的一個簡單鍵值格式,就像這樣:

{
    "memberGoods.title":[
        "商品A",
        "商品B"
    ],
    "memberGoods.brand":[
        "a",
        "b"
    ],
    "groupId":"A"
}

顯然,如上的數據損失了同一商品數據之間的關聯性,從而出現了交叉匹配的現象,爲解決這一問題,nested Object應運而生,它保留了子文檔數據中的關聯性,如果memberGoods的數據格式被定義爲nested,那麼每一個nested object 將會作爲一個隱藏的單獨文本建立索引。如下:

{
     "groupId":"A"
},
{
     "memberGoods.title":"商品A",
     "memberGoods.brand":"a"
},
{
     "memberGoods.title":"商品B",
     "memberGoods.brand":"b"
}

通過分開給每個nested object建索引,object內部的字段間的關係就能保持。當執行查詢時,只會匹配’match’同時出現在相同的nested object的結果。

不僅如此,由於nested objects 建索引的方式,在查詢的時候將根文本和nested文檔拼接是很快的,就跟把他們當成一個單獨的文本一樣的快。

 

nested object作爲一個獨立隱藏文檔單獨建索引,因此,我們不能直接查詢它們。取而代之,我們必須使用nested查詢或者nested filter來接觸它們,java語言描述如下:

  queryBuilder.must(QueryBuilders.nestedQuery("memberGoods"/** nested 字段*/,
                        QueryBuilders.matchPhraseQuery("memberGoods.title", "商品A"), ScoreMode.Avg));

其中memberGoods是父字段,memberGoods.title是子字段,以上已有提及,最後的參數ScoreMode.Avg是父文檔匹配分數的設定,(Parent hit's score is the average/max/sum/min of all child scores.)

 

此外,nested形式的查詢也有一些需要注意的缺點:

1.增加,改變或者刪除一個nested文本,整個文本必須重新建索引。nested文本越多,代價越大。

2.檢索請求會返回整個文本,而不僅是匹配的nested文本。儘管有計劃正在執行以能夠支持返回根文本的同時返回最匹配的nested文本,但目前還未實現。

如果原來類型不是nested,可以使用elasticsearch動態模板設置字段類型nested

{
  "index_patterns": [
    "*"
  ],
  "order": 0,
  "version": 1,
  "mappings": {
    "dynamic_templates": [
      {
        "nested_fields": {
          "match": "*_nested",
          "mapping": {
            "type": "nested"
          }
        }
      }
    ]
  }
}

原文:https://www.cnblogs.com/just84/p/10936034.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章