java – 使用带有嵌套对象的Criteria的spring-data-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.

在这个例子中,我使用Repository来保存我的嵌套实体.

我使用了两种(两种都不工作的)方法来查询嵌套对象:

        /*
         * 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()))));

    }

UPDATE2:
感谢Mohsin Husen,我能够使用嵌套搜索.按时间范围搜索现在有效.
除了Mohsin的建议,我还必须改变创建和启动本地Elasticsearch实例的方式:

elasticSearchNode = NodeBuilder.nodeBuilder().clusterName("foodtruck-test").local(true).build();

如果不给出clusterName,则不会创建嵌套文档.

我的下一个(希望是最后一个)问题是使用geo_distance搜索过滤器.如果我在Elasticsearch中得到了正确的结果,我会使用查询进行模糊搜索,例如’like’或’range’以及过滤器的yes / no或distance过滤器.

所以我尝试将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]]   ;
}

有没有可用的例子如何使用spring-data-elasticsearch的geo_distance(嵌套?)过滤器?

解决方法:

没有详细阅读,我在下面的代码中发现了一些问题

1)当您使用多级嵌套文档时,您必须使用快照版本(您正在使用)作为弹簧数据弹性搜索M1版本具有修复的错误. (https://jira.springsource.org/browse/DATAES-53)

2)您在实体中声明嵌套类型错误,必须如下所示

    @Field(type=FieldType.Nested)
    private LocationPoint locationPoint;

    @Field(type = FieldType.Nested)
    private TimeRange timeRange;

3)Criteria查询不处理嵌套对象,它是为处理简单实体而构建的,因为它使用query_string来查询数据.因此,使用elasticsearchTemplate或repository来查询嵌套对象.

4)您必须为嵌套对象指定完整路径

例如,在搜索locationPoint.timeRange.from和locationPoint.timeRange.to时,您必须使用如下

 String startTimePath = "locationPoint.timeRange.from";
    String endTimePath = "locationPoint.timeRange.to";

    searchQuery.must(nestedQuery(
            "locationPoint.timeRange",
            boolQuery().should(
                    rangeQuery(startTimePath).from(
                            searchTimeRange.getFrom().getTime()).to(
                            searchTimeRange.getTo().getTime())).should(
                    rangeQuery(endTimePath).from(
                            searchTimeRange.getFrom()).to(
                            searchTimeRange.getTo()))));

希望这能解决您的问题.

上一篇:如何使用变量名访问Javascript循环中嵌套对象内的元素?


下一篇:从零开始的Java项目实践-00