【发布时间】:2014-03-13 18:48:58
【问题描述】:
我对 elasticsearch 和 spring-data-elasticsearch 还是很陌生,在查询嵌套对象时遇到了一些问题。
我使用 ElasticSearch 存储库将嵌套模型实例保存在 elasticsearch 中。结果,elasticsearch 中只有一个条目包含所有数据,据我了解,这意味着我有一个嵌套文档。
我需要使用 Criteria 实现一个相对复杂的查询来迭代地构建查询。 当我尝试使用点符号访问嵌套属性时,例如
startPoint.providingTimeRange.startTime
我没有得到任何搜索结果(但在 elasticsearch 中存在匹配的数据)。
在Spring Data Elastic Search with Nested Fields and mapping 中,我发现spring-data-elasticsearch 可以使用nestedQuery 查询嵌套对象。
有没有办法将 Criteria 搜索与nestedQuery 结合起来?
提前谢谢你, 克里斯托夫
更新 1: 为了提供一些示例代码,我创建了一个演示项目,其中包含与我的真实项目中类似的嵌套对象:https://github.com/empulse-gmbh/elasticsearchtest
该示例将要查找特定时间、特定地点的 FoodTrucks。
在这个例子中,我使用了一个存储库来保存我的嵌套实体。
我使用了两种(都不起作用)方法来查询嵌套对象:
/*
* add search criteria by timerange. it is assumed in timerange from
* is always before to.
*/
TimeRange searchTimeRange = foodTruckSearch.getSearchTimeRange();
if (searchTimeRange != null) {
String startTimePath = "locationPoint.timeRange.from";
String endTimePath = "locationPoint.timeRange.to";
searchCriteria = searchCriteria.and(
new Criteria(startTimePath).between(searchTimeRange
.getFrom().getTime(), searchTimeRange.getTo()
.getTime())).or(
new Criteria(endTimePath).between(searchTimeRange
.getFrom().getTime(), searchTimeRange.getTo()
.getTime()));
}
和:
TimeRange searchTimeRange = foodTruckSearch.getSearchTimeRange();
if (searchTimeRange != null) {
String startTimePath = "locationPoint.timeRange.from";
String endTimePath = "locationPoint.timeRange.to";
searchQuery.must(nestedQuery(
"locationPoint",
boolQuery().should(
rangeQuery(startTimePath).from(
searchTimeRange.getFrom().getTime()).to(
searchTimeRange.getTo().getTime())).should(
rangeQuery(endTimePath).from(
searchTimeRange.getFrom()).to(
searchTimeRange.getTo()))));
}
更新 2: 感谢 Mohsin Husen,我能够使用嵌套搜索。按时间范围搜索现在有效。 除了 Mohsin 的建议之外,我还必须更改创建和启动本地 Elasticsearch 实例的方式:
elasticSearchNode = NodeBuilder.nodeBuilder().clusterName("foodtruck-test").local(true).build();
没有给出clusterName的嵌套文档不会被创建。
我的下一个(希望是最后一个)问题是使用 geo_distance 搜索过滤器。如果我在 Elasticsearch 中做对了,我会使用模糊搜索查询,例如“like”或“range”,并使用过滤器过滤是/否或距离过滤器。
所以我尝试将 QueryBuilder 和 FilterBuilder 与 spring-data-elasticsearch 一起使用,但失败了。
根据文档中的示例,我重构了我的模型,因此 Location 类使用 spring-data-elasticsearch 对象 GeoPoint。
我用这个来搜索:
/*
* add search criteria for radius search
*/
FilterBuilder searchFilter = null;
if (foodTruckSearch.getLatitude() != null
&& foodTruckSearch.getLongitude() != null) {
if (foodTruckSearch.getSearchRadiusInKilometers() == null) {
foodTruckSearch.setSearchRadiusInKilometers(5);
}
searchFilter = geoDistanceFilter("location.point")
.distance(
foodTruckSearch.getSearchRadiusInKilometers()
+ "km").lat(foodTruckSearch.getLatitude())
.lon(foodTruckSearch.getLongitude());
}
if (searchFilter != null) {
NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(
searchQuery, searchFilter);
return IteratorUtils.toList(foodTruckRepository.search(
nativeSearchQuery).iterator());
} else {
return IteratorUtils.toList(foodTruckRepository.search(searchQuery)
.iterator());
}
我得到的例外是:
org.elasticsearch.action.search.SearchPhaseExecutionException: Failedtoexecutephase[query_fetch],
allshardsfailed;shardFailures{
[1][searchexample][0]: SearchParseException[[searchexample][0]: query[MatchNoDocsQuery],
from[0],
size[10]: ParseFailure[Failedtoparsesource[{
"from": 0,
"size": 10,
"query": {
"bool": {
}
},
"post_filter": {
"geo_distance": {
"location.point": [6.9599115,
50.9406645],
"distance": "10km"
}
}
}]]];nested: QueryParsingException[[searchexample]failedtofindgeo_pointfield[location.point]] ;
}
是否有任何示例可用于如何将 geo_distance(嵌套?)过滤器与 spring-data-elasticsearch 一起使用?
【问题讨论】:
-
请分享一些代码,以便我们帮助解决问题。即实体和搜索请求等。
-
@MohsinHusen 请看我的Update1,一个完整的demo项目现已发布
标签: java spring nested elasticsearch spring-data