日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Elasticsearch嵌套查询

發布時間:2023/12/9 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Elasticsearch嵌套查询 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

一、背景

最近在做基于宴會廳檔期的商戶搜索推薦時,如果用傳統平鋪式的mapping結構,無法滿足需求場景,于是用到了Elasticsearch支持的Nested(嵌套)查詢。

二、普通對象與嵌套對象的索引異同

如果一個對象不是嵌套類型,那么以如下原數據為例:

PUT /my_index/blogpost/1 { "title":"Nest eggs", "body": "Making your money work...", "tags": [ "cash", "shares" ], "comments":[ { "name": "John Smith", "comment": "Great article", "age": 28, "stars": 4, "date": "2014-09-01" }, { "name": "Alice White", "comment": "More like this please", "age": 31, "stars": 5, "date": "2014-10-22" } ] }

由于是json格式的結構化文檔,es會平整成索引內的一個簡單鍵值格式,如下:

{ "title": [ eggs, nest ], "body": [ making, money, work, your ], "tags": [ cash, shares ], "comments.name": [ alice, john, smith, white ], "comments.comment": [ article, great, like, more, please, this ], "comments.age": [ 28, 31 ], "comments.stars": [ 4, 5 ], "comments.date": [ 2014-09-01, 2014-10-22 ] }

這樣的話,像這種john/28,Alice/31間的關聯性就丟失了,Nested Object就是為了解決這個問題。

將comments指定為Nested類型,如下mapping:

curl -XPUT 'localhost:9200/my_index' -d ' { "mappings":{ "blogpost":{ "properties":{ "comments":{ "type":"nested", //聲明為nested類型"properties":{ "name": {"type":"string"}, "comment": { "type": "string"}, "age": { "type": "short"}, "stars": { "type": "short"}, "date": { "type": "date"} } } } } } }

這樣,每一個nested對象將會作為一個隱藏的單獨文本建立索引,進而保持了nested對象的內在關聯關系,如下:

{ ① "comments.name": [ john, smith ], "comments.comment": [ article, great ], "comments.age": [ 28 ], "comments.stars": [ 4 ], "comments.date": [ 2014-09-01 ] } { "comments.name": [ alice, white ], "comments.comment": [ like,more,please,this], "comments.age": [ 31 ],"comments.stars": [ 5 ], "comments.date": [ 2014-10-22 ] } { "title": [ eggs, nest ], "body": [ making, money, work, your ], "tags": [ cash, shares ] } ①nested object

三、嵌套對象的查詢

命令查詢(輸出結果1):

curl -XGET localhost:9200/yzsshopv1/shop/_search?pretty -d '{"query" : {"bool" : {"filter" : {"nested" : {"path":"hallList","query":{"bool":{"filter":{"term":{"hallList.capacityMin" : "11"}}}}}}}}}' {"took" : 3,"timed_out" : false,"_shards" : {"total" : 5,"successful" : 5,"failed" : 0},"hits" : {"total" : 1,"max_score" : 0.0,"hits" : [ {"_index" : "yzsshopv1","_type" : "shop","_id" : "89999988","_score" : 0.0,"_source" : {"cityId" : "1","shopName" : "xxxx婚宴(yyyy店)","shopId" : "89999988","categoryId" : [ "55", "165", "2738" ],"hallList" : [ {"hallId" : "20625","schedule" : ["2017-11-10", "2017-11-09"],"capacityMax" : 16,"capacityMin" : 12}, {"hallId" : "21080","schedule" : [ "2017-12-10", "2017-09-09", "2017-02-25"],"capacityMax" : 20,"capacityMin" : 11} ],"wedHotelTagValue" : [ "12087", "9601", "9603", "9602" ],"regionId" : [ "9", "824" ]}} ]} }

java api查詢封裝:

BoolQueryBuilder boolBuilder = new BoolQueryBuilder(); NestedQueryBuilder nestedQuery = new NestedQueryBuilder("hallList", new TermQueryBuilder("hallList.capacityMin","11")); //注意:除path之外,fieldName也要帶上path (hallList)boolBuilder.filter(nestedQuery); searchRequest.setQuery(boolBuilder); //設置查詢條件

java api輸出字段封裝:

searchRequest.addField("shopId"); searchRequest.addField("hallList. schedule"); searchRequest.addField("hallList.capacityMin"); searchRequest.addField("hallList.capacityMax");

如果輸出的outputField為searchRequest.addField("hallList"),則會報錯:illegal_argument_exception,reason:field [hallList] isn't a leaf field;

如果輸出的outputField為searchRequest.addField("capacityMin"),則不報錯,但沒有capacityMin字段的值;

正確調用search后的輸出結果(輸出結果2):

{"took" : 8,"timed_out" : false,"_shards" : {"total" : 5,"successful" : 5,"failed" : 0},"hits" : {"total" : 1,"max_score" : 0.0,"hits" : [{"_index" : "yzsshopv1","_type" : "shop","_id" : "89999988","_score" : 0.0,"fields" : {"shopId" : [ "89999988" ],"hallList.hallId" : [ "20625", "21080"],"hallList.capacityMin" : [12, 11 ],"hallList.capacityMax" : [16, 20 ],"hallList.schedule" : [ "2017-11-10", "2017-11-09", "2017-12-10", "2017-09-09", "2017-02-25"]}}]} }

對比輸出結果1和2發現,命令輸出嵌套對象結果1沒問題,但通過java api輸出結果2時,嵌套對象內部的關系也會打亂,比如hallList.schedule字段,無法區分到底哪些值屬于hallList.hallId-20625,哪些屬于21080。

//============以下更新20170331===========

經過后續調試,發現要讓java api輸出正確結果的嵌套對象,不能通過searchRequest.addField的方式,因為嵌套對象并不是葉子節點,需要通過以下的方式添加輸出字段:

searchRequest.setFetchSource(new String[]{"shopId","hallList"},new String[]{});

還有一個不足點是: 嵌套查詢請求返回的是整個文本,而不僅是匹配的nested文本。

四、參考文檔

  • https://www.elastic.co/guide/en/elasticsearch/guide/master/nested-objects.html
  • http://stackoverflow.com/questions/23562192/unable-to-retrieve-nested-objects-using-elasticsearch-java-api
  • http://elasticsearch.cn/book/elasticsearch_definitive_guide_2.x/nested-aggregation.html
  • 轉載于:https://my.oschina.net/weiweiblog/blog/1572727

    總結

    以上是生活随笔為你收集整理的Elasticsearch嵌套查询的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。