DATAMONGO-2488 - Fix nested array path field name mapping.
Original pull request: #841.
This commit is contained in:
committed by
Mark Paluch
parent
5a49aa6519
commit
7f7be5e47d
@@ -24,7 +24,6 @@ import org.bson.BsonValue;
|
|||||||
import org.bson.Document;
|
import org.bson.Document;
|
||||||
import org.bson.conversions.Bson;
|
import org.bson.conversions.Bson;
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
|
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.core.convert.converter.Converter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
import org.springframework.data.domain.Example;
|
import org.springframework.data.domain.Example;
|
||||||
@@ -175,7 +174,7 @@ public class QueryMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Document mappedSort = new Document();
|
Document mappedSort = new Document();
|
||||||
for(Map.Entry<String,Object> entry : BsonUtils.asMap(sortObject).entrySet()) {
|
for (Map.Entry<String, Object> entry : BsonUtils.asMap(sortObject).entrySet()) {
|
||||||
|
|
||||||
Field field = createPropertyField(entity, entry.getKey(), mappingContext);
|
Field field = createPropertyField(entity, entry.getKey(), mappingContext);
|
||||||
mappedSort.put(field.getMappedKey(), entry.getValue());
|
mappedSort.put(field.getMappedKey(), entry.getValue());
|
||||||
@@ -1158,7 +1157,7 @@ public class QueryMapper {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
protected Converter<MongoPersistentProperty, String> getPropertyConverter() {
|
protected Converter<MongoPersistentProperty, String> getPropertyConverter() {
|
||||||
return new PositionParameterRetainingPropertyKeyConverter(name);
|
return new PositionParameterRetainingPropertyKeyConverter(name, mappingContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1172,6 +1171,10 @@ public class QueryMapper {
|
|||||||
return new AssociationConverter(getAssociation());
|
return new AssociationConverter(getAssociation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> getMappingContext() {
|
||||||
|
return mappingContext;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @since 1.8
|
* @since 1.8
|
||||||
@@ -1180,8 +1183,9 @@ public class QueryMapper {
|
|||||||
|
|
||||||
private final KeyMapper keyMapper;
|
private final KeyMapper keyMapper;
|
||||||
|
|
||||||
public PositionParameterRetainingPropertyKeyConverter(String rawKey) {
|
public PositionParameterRetainingPropertyKeyConverter(String rawKey,
|
||||||
this.keyMapper = new KeyMapper(rawKey);
|
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> ctx) {
|
||||||
|
this.keyMapper = new KeyMapper(rawKey, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1222,11 +1226,14 @@ public class QueryMapper {
|
|||||||
static class KeyMapper {
|
static class KeyMapper {
|
||||||
|
|
||||||
private final Iterator<String> iterator;
|
private final Iterator<String> iterator;
|
||||||
|
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||||
|
|
||||||
public KeyMapper(String key) {
|
public KeyMapper(String key,
|
||||||
|
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
|
||||||
|
|
||||||
this.iterator = Arrays.asList(key.split("\\.")).iterator();
|
this.iterator = Arrays.asList(key.split("\\.")).iterator();
|
||||||
this.iterator.next();
|
this.iterator.next();
|
||||||
|
this.mappingContext = mappingContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1240,9 +1247,22 @@ public class QueryMapper {
|
|||||||
StringBuilder mappedName = new StringBuilder(PropertyToFieldNameConverter.INSTANCE.convert(property));
|
StringBuilder mappedName = new StringBuilder(PropertyToFieldNameConverter.INSTANCE.convert(property));
|
||||||
boolean inspect = iterator.hasNext();
|
boolean inspect = iterator.hasNext();
|
||||||
|
|
||||||
|
int depth = 0;
|
||||||
while (inspect) {
|
while (inspect) {
|
||||||
|
|
||||||
String partial = iterator.next();
|
String partial = iterator.next();
|
||||||
|
|
||||||
|
if (depth > 0 && property.isCollectionLike()) {
|
||||||
|
|
||||||
|
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(property.getComponentType());
|
||||||
|
if (persistentEntity != null) {
|
||||||
|
MongoPersistentProperty persistentProperty = persistentEntity.getPersistentProperty(partial);
|
||||||
|
if(persistentProperty != null) {
|
||||||
|
partial = mapPropertyName(persistentProperty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boolean isPositional = (isPositionalParameter(partial) && (property.isMap() || property.isCollectionLike()));
|
boolean isPositional = (isPositionalParameter(partial) && (property.isMap() || property.isCollectionLike()));
|
||||||
|
|
||||||
if (isPositional) {
|
if (isPositional) {
|
||||||
@@ -1250,6 +1270,7 @@ public class QueryMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inspect = isPositional && iterator.hasNext();
|
inspect = isPositional && iterator.hasNext();
|
||||||
|
depth++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mappedName.toString();
|
return mappedName.toString();
|
||||||
|
|||||||
@@ -308,7 +308,7 @@ public class UpdateMapper extends QueryMapper {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected Converter<MongoPersistentProperty, String> getPropertyConverter() {
|
protected Converter<MongoPersistentProperty, String> getPropertyConverter() {
|
||||||
return new PositionParameterRetainingPropertyKeyConverter(key);
|
return new PositionParameterRetainingPropertyKeyConverter(key, getMappingContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -317,7 +317,7 @@ public class UpdateMapper extends QueryMapper {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected Converter<MongoPersistentProperty, String> getAssociationConverter() {
|
protected Converter<MongoPersistentProperty, String> getAssociationConverter() {
|
||||||
return new UpdateAssociationConverter(getAssociation(), key);
|
return new UpdateAssociationConverter(getMappingContext(), getAssociation(), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -334,10 +334,12 @@ public class UpdateMapper extends QueryMapper {
|
|||||||
*
|
*
|
||||||
* @param association must not be {@literal null}.
|
* @param association must not be {@literal null}.
|
||||||
*/
|
*/
|
||||||
public UpdateAssociationConverter(Association<MongoPersistentProperty> association, String key) {
|
public UpdateAssociationConverter(
|
||||||
|
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext,
|
||||||
|
Association<MongoPersistentProperty> association, String key) {
|
||||||
|
|
||||||
super(association);
|
super(association);
|
||||||
this.mapper = new KeyMapper(key);
|
this.mapper = new KeyMapper(key, mappingContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
import org.springframework.data.annotation.Id;
|
import org.springframework.data.annotation.Id;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.data.domain.Sort.Direction;
|
import org.springframework.data.domain.Sort.Direction;
|
||||||
@@ -927,6 +926,70 @@ public class QueryMapperUnitTests {
|
|||||||
assertThat(target).isEqualTo(org.bson.Document.parse("{\"_id\": {\"$in\": [{\"$oid\": \"" + id + "\"}]}}"));
|
assertThat(target).isEqualTo(org.bson.Document.parse("{\"_id\": {\"$in\": [{\"$oid\": \"" + id + "\"}]}}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // DATAMONGO-2488
|
||||||
|
public void mapsNestedArrayPathCorrectlyForNonMatchingPath() {
|
||||||
|
|
||||||
|
org.bson.Document target = mapper.getMappedObject(
|
||||||
|
query(where("array.$[some_item].nested.$[other_item]").is("value")).getQueryObject(),
|
||||||
|
context.getPersistentEntity(Foo.class));
|
||||||
|
|
||||||
|
assertThat(target).isEqualTo(new org.bson.Document("array.$[some_item].nested.$[other_item]", "value"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // DATAMONGO-2488
|
||||||
|
public void mapsNestedArrayPathCorrectlyForObjectTargetArray() {
|
||||||
|
|
||||||
|
org.bson.Document target = mapper.getMappedObject(
|
||||||
|
query(where("arrayObj.$[some_item].nested.$[other_item]").is("value")).getQueryObject(),
|
||||||
|
context.getPersistentEntity(WithNestedArray.class));
|
||||||
|
|
||||||
|
assertThat(target).isEqualTo(new org.bson.Document("arrayObj.$[some_item].nested.$[other_item]", "value"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // DATAMONGO-2488
|
||||||
|
public void mapsNestedArrayPathCorrectlyForStringTargetArray() {
|
||||||
|
|
||||||
|
org.bson.Document target = mapper.getMappedObject(
|
||||||
|
query(where("arrayString.$[some_item].nested.$[other_item]").is("value")).getQueryObject(),
|
||||||
|
context.getPersistentEntity(WithNestedArray.class));
|
||||||
|
|
||||||
|
assertThat(target).isEqualTo(new org.bson.Document("arrayString.$[some_item].nested.$[other_item]", "value"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // DATAMONGO-2488
|
||||||
|
public void mapsCustomFieldNamesForNestedArrayPathCorrectly() {
|
||||||
|
|
||||||
|
org.bson.Document target = mapper.getMappedObject(
|
||||||
|
query(where("arrayCustomName.$[some_item].nested.$[other_item]").is("value")).getQueryObject(),
|
||||||
|
context.getPersistentEntity(WithNestedArray.class));
|
||||||
|
|
||||||
|
assertThat(target).isEqualTo(new org.bson.Document("arrayCustomName.$[some_item].nes-ted.$[other_item]", "value"));
|
||||||
|
}
|
||||||
|
|
||||||
|
class WithNestedArray {
|
||||||
|
|
||||||
|
List<NestedArrayOfObj> arrayObj;
|
||||||
|
List<NestedArrayOfString> arrayString;
|
||||||
|
List<NestedArrayOfObjCustomFieldName> arrayCustomName;
|
||||||
|
}
|
||||||
|
|
||||||
|
class NestedArrayOfObj {
|
||||||
|
List<ArrayObj> nested;
|
||||||
|
}
|
||||||
|
|
||||||
|
class NestedArrayOfObjCustomFieldName {
|
||||||
|
|
||||||
|
@Field("nes-ted") List<ArrayObj> nested;
|
||||||
|
}
|
||||||
|
|
||||||
|
class NestedArrayOfString {
|
||||||
|
List<String> nested;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ArrayObj {
|
||||||
|
String foo;
|
||||||
|
}
|
||||||
|
|
||||||
@Document
|
@Document
|
||||||
class Foo {
|
class Foo {
|
||||||
@Id private ObjectId id;
|
@Id private ObjectId id;
|
||||||
|
|||||||
Reference in New Issue
Block a user