From d92f4150b778911f837250596fef4e5506fc77ec Mon Sep 17 00:00:00 2001 From: "mohsin.husen" Date: Wed, 12 Feb 2014 20:59:44 +0000 Subject: [PATCH] DATAES-48 - Mapping for multiple level nested document is getting created wrong --- .../elasticsearch/core/MappingBuilder.java | 22 ++--- .../data/elasticsearch/Book.java | 5 +- .../data/elasticsearch/InnerObjectTests.java | 69 +++++++++++++ .../data/elasticsearch/NestedObjectTests.java | 98 +++++++++++++++---- .../data/elasticsearch/Person.java | 13 ++- .../PersonMultipleLevelNested.java | 11 +++ 6 files changed, 184 insertions(+), 34 deletions(-) create mode 100644 src/test/java/org/springframework/data/elasticsearch/InnerObjectTests.java diff --git a/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java b/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java index 65fb86d75..085bf8f22 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -67,20 +67,20 @@ class MappingBuilder { // Properties XContentBuilder xContentBuilder = mapping.startObject(FIELD_PROPERTIES); - mapEntity(xContentBuilder, clazz, true, idFieldName, EMPTY, false); + mapEntity(xContentBuilder, clazz, true, idFieldName, EMPTY, false, FieldType.Auto); return xContentBuilder.endObject().endObject().endObject(); } private static void mapEntity(XContentBuilder xContentBuilder, Class clazz, boolean isRootObject, String idFieldName, - String nestedObjectFieldName, boolean nestedAnnotaion) throws IOException { + String nestedObjectFieldName, boolean nestedOrObjectField, FieldType fieldType) throws IOException { java.lang.reflect.Field[] fields = clazz.getDeclaredFields(); - if (!isRootObject && (isAnyPropertyAnnotatedAsField(fields) || nestedAnnotaion)) { + if (!isRootObject && (isAnyPropertyAnnotatedAsField(fields) || nestedOrObjectField)) { String type = FieldType.Object.toString().toLowerCase(); - if (nestedAnnotaion) { - type = FieldType.Nested.toString().toLowerCase(); + if (nestedOrObjectField) { + type = fieldType.toString().toLowerCase(); } xContentBuilder.startObject(nestedObjectFieldName).field(FIELD_TYPE, type).startObject(FIELD_PROPERTIES); } @@ -98,9 +98,9 @@ class MappingBuilder { if (singleField == null) { continue; } - boolean nestedField = isNestedField(field); - mapEntity(xContentBuilder, getFieldType(field), false, EMPTY, field.getName(), nestedField); - if (nestedField) { + boolean nestedOrObject = isNestedOrObjectField(field); + mapEntity(xContentBuilder, getFieldType(field), false, EMPTY, field.getName(), nestedOrObject, field.getAnnotation(Field.class).type()); + if (nestedOrObject) { continue; } } @@ -120,7 +120,7 @@ class MappingBuilder { } } - if (!isRootObject && isAnyPropertyAnnotatedAsField(fields)) { + if (!isRootObject && isAnyPropertyAnnotatedAsField(fields) || nestedOrObjectField) { xContentBuilder.endObject().endObject(); } } @@ -296,7 +296,7 @@ class MappingBuilder { return false; } - private static boolean isNestedField(java.lang.reflect.Field field) { + private static boolean isNestedOrObjectField(java.lang.reflect.Field field) { Field fieldAnnotation = field.getAnnotation(Field.class); return fieldAnnotation != null && (FieldType.Nested == fieldAnnotation.type() || FieldType.Object == fieldAnnotation.type()); } diff --git a/src/test/java/org/springframework/data/elasticsearch/Book.java b/src/test/java/org/springframework/data/elasticsearch/Book.java index fad247f40..750ef8982 100644 --- a/src/test/java/org/springframework/data/elasticsearch/Book.java +++ b/src/test/java/org/springframework/data/elasticsearch/Book.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,8 @@ package org.springframework.data.elasticsearch; 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; /** * @author Rizwan Idrees @@ -28,6 +30,7 @@ public class Book { @Id private String id; private String name; + @Field(type = FieldType.Object) private Author author; public String getId() { diff --git a/src/test/java/org/springframework/data/elasticsearch/InnerObjectTests.java b/src/test/java/org/springframework/data/elasticsearch/InnerObjectTests.java new file mode 100644 index 000000000..85a9008b7 --- /dev/null +++ b/src/test/java/org/springframework/data/elasticsearch/InnerObjectTests.java @@ -0,0 +1,69 @@ +/* + * Copyright 2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.elasticsearch; + +import static org.apache.commons.lang.RandomStringUtils.*; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; +import org.springframework.data.elasticsearch.repositories.SampleElasticSearchBookRepository; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Mohsin Husen + */ + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath:/repository-test-nested-object.xml") +public class InnerObjectTests { + + @Autowired + private SampleElasticSearchBookRepository bookRepository; + + @Autowired + private ElasticsearchTemplate elasticsearchTemplate; + + @Before + public void before() { + elasticsearchTemplate.deleteIndex(Book.class); + elasticsearchTemplate.createIndex(Book.class); + elasticsearchTemplate.refresh(Book.class, true); + } + + @Test + public void shouldIndexInnerObject() { + // given + String id = randomAlphanumeric(5); + Book book = new Book(); + book.setId(id); + book.setName("xyz"); + Author author = new Author(); + author.setId("1"); + author.setName("ABC"); + book.setAuthor(author); + // when + bookRepository.save(book); + // then + assertThat(bookRepository.findOne(id), is(notNullValue())); + } +} diff --git a/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java b/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java index ab2c5fadb..89efe0890 100644 --- a/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java @@ -15,7 +15,6 @@ */ package org.springframework.data.elasticsearch; -import static org.apache.commons.lang.RandomStringUtils.*; import static org.elasticsearch.index.query.QueryBuilders.*; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; @@ -36,7 +35,6 @@ import org.springframework.data.elasticsearch.core.query.GetQuery; import org.springframework.data.elasticsearch.core.query.IndexQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.query.SearchQuery; -import org.springframework.data.elasticsearch.repositories.SampleElasticSearchBookRepository; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -49,9 +47,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration("classpath:/repository-test-nested-object.xml") public class NestedObjectTests { - @Autowired - private SampleElasticSearchBookRepository bookRepository; - @Autowired private ElasticsearchTemplate elasticsearchTemplate; @@ -172,22 +167,6 @@ public class NestedObjectTests { assertThat(personIndexed.getContent().get(0).getId(), is("1")); } - @Test - public void shouldIndexInnerObject() { - // given - String id = randomAlphanumeric(5); - Book book = new Book(); - book.setId(id); - book.setName("xyz"); - Author author = new Author(); - author.setId("1"); - author.setName("ABC"); - book.setAuthor(author); - // when - bookRepository.save(book); - // then - assertThat(bookRepository.findOne(id), is(notNullValue())); - } private List createPerson() { @@ -245,4 +224,81 @@ public class NestedObjectTests { return indexQueries; } + + @Test + public void shouldSearchBooksForPersonInitialLevelNestedType() { + + List cars = new ArrayList(); + + Car saturn = new Car(); + saturn.setName("Saturn"); + saturn.setModel("SL"); + + Car subaru = new Car(); + subaru.setName("Subaru"); + subaru.setModel("Imprezza"); + + Car ford = new Car(); + ford.setName("Ford"); + ford.setModel("Focus"); + + cars.add(saturn); + cars.add(subaru); + cars.add(ford); + + Book java = new Book(); + java.setId("1"); + java.setName("java"); + Author javaAuthor = new Author(); + javaAuthor.setId("1"); + javaAuthor.setName("javaAuthor"); + java.setAuthor(javaAuthor); + + Book spring= new Book(); + spring.setId("2"); + spring.setName("spring"); + Author springAuthor = new Author(); + springAuthor.setId("2"); + springAuthor.setName("springAuthor"); + spring.setAuthor(springAuthor); + + Person foo = new Person(); + foo.setName("Foo"); + foo.setId("1"); + foo.setCar(cars); + foo.setBooks(Arrays.asList(java, spring)); + + Car car = new Car(); + car.setName("Saturn"); + car.setModel("Imprezza"); + + Person bar = new Person(); + bar.setId("2"); + bar.setName("Bar"); + bar.setCar(Arrays.asList(car)); + + List indexQueries = new ArrayList(); + IndexQuery indexQuery1 = new IndexQuery(); + indexQuery1.setId(foo.getId()); + indexQuery1.setObject(foo); + + IndexQuery indexQuery2 = new IndexQuery(); + indexQuery2.setId(bar.getId()); + indexQuery2.setObject(bar); + + indexQueries.add(indexQuery1); + indexQueries.add(indexQuery2); + + elasticsearchTemplate.putMapping(Person.class); + elasticsearchTemplate.bulkIndex(indexQueries); + elasticsearchTemplate.refresh(Person.class, true); + + QueryBuilder builder = nestedQuery("books", boolQuery().must(termQuery("books.name", "java"))); + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder).build(); + List persons = elasticsearchTemplate.queryForList(searchQuery, Person.class); + + assertThat(persons.size(), is(1)); + + } } diff --git a/src/test/java/org/springframework/data/elasticsearch/Person.java b/src/test/java/org/springframework/data/elasticsearch/Person.java index f8f2530ec..4a157936f 100644 --- a/src/test/java/org/springframework/data/elasticsearch/Person.java +++ b/src/test/java/org/springframework/data/elasticsearch/Person.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,6 +40,9 @@ public class Person { @Field(type = FieldType.Nested) private List car; + @Field(type = FieldType.Nested) + private List books; + public String getId() { return id; } @@ -63,4 +66,12 @@ public class Person { public void setCar(List car) { this.car = car; } + + public List getBooks() { + return books; + } + + public void setBooks(List books) { + this.books = books; + } } diff --git a/src/test/java/org/springframework/data/elasticsearch/PersonMultipleLevelNested.java b/src/test/java/org/springframework/data/elasticsearch/PersonMultipleLevelNested.java index 00243d34c..76e9fdabf 100644 --- a/src/test/java/org/springframework/data/elasticsearch/PersonMultipleLevelNested.java +++ b/src/test/java/org/springframework/data/elasticsearch/PersonMultipleLevelNested.java @@ -40,6 +40,9 @@ public class PersonMultipleLevelNested { @Field(type = FieldType.Nested) private List girlFriends; + @Field(type = FieldType.Nested) + private List cars; + public String getId() { return id; } @@ -63,4 +66,12 @@ public class PersonMultipleLevelNested { public void setGirlFriends(List girlFriends) { this.girlFriends = girlFriends; } + + public List getCars() { + return cars; + } + + public void setCars(List cars) { + this.cars = cars; + } }