DATAES-48 - Mapping for multiple level nested document is getting created wrong

This commit is contained in:
mohsin.husen 2014-02-12 20:59:44 +00:00
parent e9a260235d
commit d92f4150b7
6 changed files with 184 additions and 34 deletions

View File

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

View File

@ -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() {

View File

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

View File

@ -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<IndexQuery> createPerson() {
@ -245,4 +224,81 @@ public class NestedObjectTests {
return indexQueries;
}
@Test
public void shouldSearchBooksForPersonInitialLevelNestedType() {
List<Car> cars = new ArrayList<Car>();
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<IndexQuery> indexQueries = new ArrayList<IndexQuery>();
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<Person> persons = elasticsearchTemplate.queryForList(searchQuery, Person.class);
assertThat(persons.size(), is(1));
}
}

View File

@ -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> car;
@Field(type = FieldType.Nested)
private List<Book> books;
public String getId() {
return id;
}
@ -63,4 +66,12 @@ public class Person {
public void setCar(List<Car> car) {
this.car = car;
}
public List<Book> getBooks() {
return books;
}
public void setBooks(List<Book> books) {
this.books = books;
}
}

View File

@ -40,6 +40,9 @@ public class PersonMultipleLevelNested {
@Field(type = FieldType.Nested)
private List<GirlFriend> girlFriends;
@Field(type = FieldType.Nested)
private List<Car> cars;
public String getId() {
return id;
}
@ -63,4 +66,12 @@ public class PersonMultipleLevelNested {
public void setGirlFriends(List<GirlFriend> girlFriends) {
this.girlFriends = girlFriends;
}
public List<Car> getCars() {
return cars;
}
public void setCars(List<Car> cars) {
this.cars = cars;
}
}