Elasticsearch nested sort filter 嵌套排序问题及解决
官方解释
首先来看1下官方文档:Sorting by Nested Fields 索引
PUT /my_index/blogpost/2 { "title": "Investment secrets","body": "What they dont tell you ...","tags": [ "shares","equities" ],"comments": [
{ "name": "Mary Brown","comment": "Lies,lies,lies","age": 42,"stars": 1,"date": "2014⑴0⑴8" },{ "name": "John Smith","comment": "Youre making it up!","age": 28,"stars": 2,"date": "2014⑴0⑴6" }
]
}
嵌套查询
GET /_search
{ "query": { "nested": { "path": "comments","filter": { "range": { "comments.date": { "gte": "2014⑴0-01","lt": "2014⑴1-01" }
}
}
}
},"sort": { "comments.stars": { "order": "asc","mode": "min","nested_filter": { "range": { "comments.date": { "gte": "2014⑴0-01","lt": "2014⑴1-01" }
}
}
}
}
}
以上是官方代码,方便打不开网页的同学查看。下面是我遇到的问题及解决方法。 记录这里只提供了RestfulAPI,我在使用java的进程中遇到了很多问题。有超过1半的时间都耗在这里了,特此记录1下。 问题
项目中使用java API,所以参照ResefulAPI写出来1段代码。
{
"sort": {
"goods_sale_number.sale_num": {
"order": "asc","nested_filter": {
"term": {
"warehouse_id": "22" } },"missing": "_last" } },"size": "99999","_source": [ "goods_sale_number","id" ] }
毛病的java代码,根据json转换的,运行后没法排序。
String flag = sortOrder.toString().equals("desc") ? "_last" : "_first";
FilterBuilder termFilter = FilterBuilders.termFilter("goods.goods_sale_number.warehouse_id",warehouseId);
searchRequestBuilder.addSort(SortBuilders.fieldSort("goods_sale_number.sale_num")
.setNestedFilter(FilterBuilders.nestedFilter("goods_sale_number",termFilter))
.setNestedPath("goods.goods_sale_number")
.order(sortOrder).missing(flag));
乍1看,其实java代码和restful的代码并没有甚么区分,但是却1直不能使用。 分析及解决问题
elasticsearch源码分析源码
package org.elasticsearch.action.search; public class SearchRequestBuilder extends ActionRequestBuilder<SearchRequest,SearchResponse,SearchRequestBuilder,Client> { ... //这个方法就是解决问题的本源 public SearchRequest request() { if(this.sourceBuilder != null) {
((SearchRequest)this.request).source(this.sourceBuilder());
} return (SearchRequest)this.request;
}
...
}
分析在此我们可以看到有1个this.sourceBuilder(),它里面的值,就是我们写的java代码,query,filter,sort 等等都会在这里转换成json,写入到searchRequestBuilder.source,而searchRequestBuilder.extraSource则是之前我写入的另外一部份json,得到这两部份值后对照1下。
//source "sort" : [ { "goods_sale_number.sale_num" : { "order" : "desc","missing" : "_last","nested_filter" : { "nested" : { "filter" : { "term" : { "goods.goods_sale_number.warehouse_id" : "22" }
},"path" : "goods_sale_number" }
},"nested_path" : "goods.goods_sale_number" }
} ]
//extraSource "sort": { "goods_sale_number.sale_num": { "order": "asc","nested_filter": { "term": { "warehouse_id": "22" }
},"missing": "_last" }
}
可以看到有明显的不同,不同就在于,中间多了几个nested的嵌套。所以分析出多是由于对英文文档理解不当,sort里面的查询并不是是嵌套查询,只是1个普通的查询。由于它本身在添加排序的时候就已是嵌套了。 修改后的java代码:
String flag = sortOrder.toString().equals("desc") ? "_last" : "_first";
FilterBuilder termFilter = FilterBuilders.termFilter("warehouse_id",warehouseId);
searchRequestBuilder.addSort(SortBuilders.fieldSort("goods_sale_number.sale_num")
.setNestedFilter(termFilter)
.order(sortOrder).missing(flag));
再次分析json:
//source "sort" : [ { "goods_sale_number.sale_num" : { "order" : "desc","nested_filter" : { "term" : { "warehouse_id" : "22" }
}
}
} ]
这1次的值和restful API 的json1模1样了。再次履行后发现正确无误。 终究正确的代码正确的java代码
String flag = sortOrder.toString().equals("desc") ? "_last" : "_first";
FilterBuilder termFilter = FilterBuilders.termFilter("warehouse_id",warehouseId);
searchRequestBuilder.addSort(SortBuilders.fieldSort("goods_sale_number.sale_num")
.setNestedFilter(termFilter)
.order(sortOrder).missing(flag));
问题总结
其间遇到的其它问题(child query must only match non-parent docs)1个毛病日志
[2015-10-20 18:15:25,553][DEBUG][action.search.type ] [local] [shop][4],node[uv2Ii94-R8a_Wk00s7bPew],[P],s[STARTED]: Failed to execute [org.elasticsearch.action.search.SearchRequest@1ba36675] org.elasticsearch.search.query.QueryPhaseExecutionException: [shop][4]: query[ConstantScore(cache(+_type:goods +org.elasticsearch.index.search.nested.NonNestedDocsFilter@5005b052))],from[0],size[10],sort[
毛病缘由
当前嵌套的字段不在父级下面。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |