Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
944 views
in Technique[技术] by (71.8m points)

elasticsearch - Spring Data Elastic Search with Nested Fields and mapping

I am using spring-data-elasticsearch and elasticsearch together to query documents. I'd like to do nested queries on nested documents.

I have this in java :

@Document(indexName = "as", type = "a", indexStoreType = "memory", shards = 1, replicas = 0, refreshInterval = "-1")
class A {

     @Id
     private String Id;

     @Field(type = String, index = analyzed, store = true)
     private String field1;

     // ... Many more Fields.

     @NestedField(type = FieldType.Object, index = analyzed, store = true, dotSuffix = "accounts")
     private List<B> bs;

     // ... getters and setters
}

And

class B { // some normal pojo }

When I let spring-data do the mapping, I get :

"a": {
    "properties": {
        "bs": {
            "properties": {
                "someBProperty": {
                    "type": "string"
                },
                "BId": {
                    "type": "string"
                }
            }
        },
        "id": { ... },
        ...
}

When I am trying to query the document, I get the classical inner vs nested documents problems and it doesn't recognize the nested element.

When I try to update mapping to use nested document I get "can't be changed from non-nested to nested".

Should I tell spring-data-es somehow that @NestedField => type: "nested" into mapping ? Is there a way to add custom mapping to spring-data when it create index & mapping ?

Also, I am initializing indexes via :

elasticsearchTemplate.deleteIndex(A.class);
elasticsearchTemplate.createIndex(A.class);
elasticsearchTemplate.putMapping(A.class);
elasticsearchTemplate.refresh(A.class,true);

And then querying using spring-data repository :

QueryBuilder builder = QueryBuilders.nestedQuery( "bs", QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("as.field1", "A1")).must(QueryBuilders.matchQuery("as.field2", "B1")));

Iterable<DenormalizedRelationshipDocument> res = aRepository.search(builder);

Here the res has 0 element in the Iterable but via REST I get the error on the nested query not supported (as I don't have it in mapping).

finally,

Does Spring-Data-ElasticSearch supports nested mappings via ES QueryBuilders API ? When should I make that mapping happens ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Spring data elasticsearch now supports most of the common feature set of elasticsearch including Nested, Inner Objects and Parent Child(recently)

Detailed explanation can be found at managing relationship in elasticsearch

Nested document Example

Person Entity



   @Document( indexName = "person" , type = "user")

    public class Person {

        @Id
        private String id;

        private String name;

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

        // setters-getters

    }

Car Entity



    public class Car {
    private String name;
    private String model;
    //setters and getters 
    }

Setting Up Data



    Person foo = new Person();
    foo.setName("Foo");
    foo.setId("1");

    List cars = new ArrayList();
    Car subaru = new Car();
    subaru.setName("Subaru");
    subaru.setModel("Imprezza");
    cars.add(subaru);
    foo.setCar(cars);

Indexing



        IndexQuery indexQuery = new IndexQuery();
        indexQuery.setId(foo.getId());
        indexQuery.setObject(foo);

       //creating mapping
       elasticsearchTemplate.putMapping(Person.class);
       //indexing document
       elasticsearchTemplate.index(indexQuery);
       //refresh
       elasticsearchTemplate.refresh(Person.class, true);

Searching

 

    QueryBuilder builder = nestedQuery("car", boolQuery().must(termQuery("car.name",      "subaru")).must(termQuery("car.model", "imprezza")));

    SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder).build();
    List persons = elasticsearchTemplate.queryForList(searchQuery, Person.class);

you can find more test cases about Nested and Inner Object at Nested Object Tests


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...