Spring Data ES 按嵌套对象日期字段查询

Spring Data ES query by nested object date field

使用 Spring Data ES.

我有一个名为 ship 的索引,其定义如下:

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

@Document(indexName = "ship", type = "journey")
public class ShipJourney {

    @Id
    private String shipId;

    @Field(type = FieldType.Nested)
    private List<ShipLocation> shipLocation;

    //getters and setters
}

ShipLocation 是嵌套对象,定义为:

import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import java.time.LocalDateTime;

public class ShipLocation {

    private double latitude;
    private double longitude;

    @Temporal(TemporalType.TIMESTAMP)
    private LocalDateTime recordedOnTime;

    //setters and getters
}

我想在 LocalDateTime 参数之前或等于

参数之前找到一个船舶位置。

我试过这个:

ShipJourney findTopByShipIdAndShipLocationRecordedOnTimeLessThanOrderByShipLocationRecordedOnTimeDesc(
        String shipId, LocalDateTime recordedOnTime);

后来才意识到我在 ShipJourney 本身上使用了 Top,由于 shipId's 的唯一性,它最终将成为一条记录。

如何根据嵌套元素的属性之一限制我为嵌套元素获取的数据?

我不确定 Spring Data ElasticSearch 存储库是否可行。如果您可以自动装配 ElasticSearchTemplate,您的查询可能看起来像这样(未经测试):

String shipId = "A";
LocalDateTime recordedOnTime = LocalDateTime.now();
int maxShipLocations = 3; // <-- TOP

NestedQueryBuilder findByLocation = nestedQuery("shipLocation", rangeQuery("shipLocation.recordedOnTime").lt(recordedOnTime));
TermQueryBuilder findById = termQuery("id", shipId);
QueryBuilder findByIdAndLocation = QueryBuilders.boolQuery()
        .filter(findById) 
        .filter(findByLocation.innerHit(new QueryInnerHitBuilder().setSize(maxShipLocations)));

SearchQuery query = new NativeSearchQueryBuilder()
        .withIndices("ship")
        .withTypes("journey")
        .withQuery(findByIdAndLocation)
        .withSort(SortBuilders.fieldSort("shipLocation.recordedOnTime").order(SortOrder.DESC))
        .build();
List<ShipJourney> shipJourney = elasticSearchTemplate.queryForList(query, ShipJourney.class);