当前位置: 首页 > 知识库问答 >
问题:

使用嵌套对象条件的spring数据elasticsearch

咸臻
2023-03-14

我对elasticsearch和spring数据elasticsearch非常陌生,在查询嵌套对象时遇到了一些问题。

我使用ElasticSearch存储库在ElasticSearch中保存一个嵌套模型实例。因此,elasticsearch中只有一个条目包含所有数据,据我所知,这意味着我有一个嵌套文档。

我需要使用Criteria实现一个相对复杂的查询来迭代构建查询。当我尝试使用点表示法访问嵌套属性时,如

startPoint.providingTimeRange.startTime

我没有得到任何搜索结果(但匹配的数据存在于elasticsearch中)。

在使用嵌套字段和映射的Spring Data Elastic Search中,我发现spring-data-elasticsearch能够使用nestedQuery查询嵌套对象。

有没有办法将标准搜索与嵌套查询结合起来?

先谢谢你克里斯托夫

更新1:为了提供一些示例代码,我创建了一个演示项目,其中包含类似于真实项目中的嵌套对象:https://github.com/empulse-gmbh/elasticsearchtest

该示例将查找在特定时间的特定地点的食品卡车。

在本例中,我使用了一个存储库来持久化嵌套的实体。

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

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

如果不提供blosterName,则不会创建嵌套文档。

我的下一个(希望是最后一个)问题是使用geo_distance搜索过滤器。如果我在Elasticsearch中做对了,我会使用查询来进行模糊搜索,如“喜欢”或“范围”,并使用是/否或距离过滤器。

所以我尝试将QueryBuilder和FilterBuilder与spring-data-elasticsearch一起使用,但失败了。

根据文档中的示例,我重构了模型,以便Location类使用spring数据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数据弹性搜索?

共有2个答案

马沛
2023-03-14

该异常是由于在中提供了默认映射器而导致的

return new ElasticsearchTemplate(elasticSearchNode.client());

删除这个错误的映射器导致spring数据elasticsearch将正确的映射放入elasticsearch。

如果要为geo\u distance search启用实体,请使用

@GeoPointField

注释以标记包含纬度/经度值的字段。

此外,FoodTruckServiceImpl被更改为使用过滤器,而不是查询。

GitHub中的项目已更新,是一个功能完整的示例。可以使用FoodTruck示例了解spring数据elasticsearch的第一步。

陈允晨
2023-03-14

在没有详细阅读的情况下,我发现了您代码中的一些问题,如下所示

1) 当您使用多级嵌套文档时,您必须使用快照版本(您正在使用),因为spring数据elasticsearch M1发行版存在已修复的错误。(https://jira.springsource.org/browse/DATAES-53)

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

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

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

3) 条件查询不会处理嵌套对象,它是为处理简单实体而构建的,因为它使用query\u string查询数据。因此,使用elasticsearchTemplate或repository来查询嵌套对象。

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

e、 g,搜索定位点时。时间范围。起点和位置点。时间范围。您必须按以下方式使用

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

希望这能解决你的问题。

 类似资料:
  • 我试图在spring数据中编写一个findBy,希望所有员工的第一部门状态都处于活动状态。是否可以使用spring数据方法名称,而不使用自定义查询? 类似于List findByDepartmentFirstStatusIsActive(); 我试了几次,但都没用,所以我想没有!!!

  • 对我如何做这件事有什么建议吗? 更新:我将如下所示的方法添加到存储库中: 但是在代码中调用此方法时,我会得到以下错误。不确定我使用的Redis/Spring库是否有问题。我在用 null 当我执行findAll,findById时,它会返回结果。当我执行findByPersonalInfo_UserId()并传递像:Anthony.Turner或Ashleigh.Hayes这样的值时,什么也不会显

  • 我有一个班级结构 我使用数据绑定,房间和匕首。我得到编译错误为找不到类数据库组件,可能是因为房间不允许持久化的嵌套对象。为了启用,我使用了@嵌入式注释,但仍然得到相同的错误。但是如果我使用@Ignore注释,指示不处理该字段的Room;编译正在成功进行。 请参阅https://developer.android.com/topic/libraries/architecture/room.html#

  • 问题内容: 我在使用hibernate标准时遇到问题。我正在尝试制定一个条件,在其中查看查询返回的类的成员对象的ID。 例如: 结果是一个例外: 该班确实包含讲座变量,又包含了admin变量。我尝试过使用,效果很好。 这样的对象层次结构可以限制的级别数是否有限制? 谢谢! 代码段: “用户”类扩展了该类,该类又扩展了一个类,该类具有以下方法: 从Hibernate映射XML: 这是表: 问题答案:

  • 我想从API中获取countynames,它返回嵌套对象; 等等,有200多个国家,每个县都有自己的“编号”。最后,我想列出所有“姓名”信息。我想我应该使用JsonDeserializer,但不幸的是我不能。

  • 我从foursquare收到了一个json形式的响应。我尝试访问对象的某些部分,但没有成功。如何访问对象的地址?这是我试过的代码。 以下是json响应的一个示例: 完整的回应可以在这里找到