简体   繁体   中英

Return only nested field from query in ElasticSearch Spring project

I have the following POJOs

@Document(indexName = "person", type = "user")
public class Person {

    @Id
    private String id;

    @Field(type = FieldType.String)
    private String name;

    @Field(type = FieldType.Nested)
    private List<Car> car;

// getter/setter

}
public class Car {

    @Field(type = FieldType.String)
    private String name;

    @Field(type = FieldType.String)
    private String model;

// getter/setter
}

And in the class below I want to retrieve the nested field "cars" directly for a given Person with the name passed as parameter but it returns a List with null value.

public class ElasticsearchRepo {

    private ElasticsearchOperations op;

    public List<Car> getCars(String name) {
        String[] includeFields = new String[]{"car"};
        String[] excludeFields = null;

        NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery("name", name))
            .withSourceFilter(new FetchSourceFilter(includeFields, excludeFields)).build();

        SearchHits<Car> searchHits = op.search(query, Car.class, IndexCoordinates.of("person"));

        return customerSearchHits.getSearchHits().stream().map(s -> s.getContent().getCars())
            .collect(Collectors.toList());
    }

However, if in the searchHits code above I change the class to Person as shown below, I will get returned the pojo Person where the property "cars" is the only one filled in (all other properties are retrieved as null):

 SearchHits<Person> searchHits = op
            .search(query, Person.class, IndexCoordinates.of("person"));

But how may I retrieve directly the nested property cars?

When querying the person index, Elasticsearch will return Person documents - with only the fields that you defined in the sourcefilter. And Spring Data Elasticsearch maps these documents to the given entity. But it cannot map a source docuument with a car property toa class having name and model properties. That's why in your first case the returned persons are mapped to empty objects.

The second way you have is the correct one: retrieve the persons and extract the cars from these objects.

If you like to do it with streams:

List<Car> cars = operations.search(query, Person.class, IndexCoordinates.of("person"))
    .stream().map(SearchHit::getContent)
    .flatMap(person -> person.getCar().stream())
    .collect(Collectors.toList());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM