Compare commits

...

8 Commits
3.2.7 ... 3.2.8

Author SHA1 Message Date
Christoph Strobl
20a8b5e5f1 Release version 3.2.8 (2021.0.8).
See #3878
2022-01-14 09:47:47 +01:00
Christoph Strobl
3c25ed8378 Prepare 3.2.8 (2021.0.8).
See #3878
2022-01-14 09:47:06 +01:00
Mark Paluch
6c21eab84b Polishing.
Simplify assertions, reformat code.

See #3921
Original pull request: #3930.
2022-01-13 11:07:21 +01:00
Christoph Strobl
f00e8ed93c Use index instead of iterator to map position and map keys for updates.
This commit removes usage of the iterator and replaces map key and positional parameter mappings with an index based token lookup.

Closes #3921
Original pull request: #3930.
2022-01-13 11:06:42 +01:00
Mark Paluch
34a35bd489 Polishing.
Tweak Javadoc.

See #3898
Original pull request: #3904.
2021-12-14 09:37:05 +01:00
Christoph Strobl
ba2b65cfd5 Fix field inclusion in aggregation project operation.
Closes #3898
Original pull request: #3904.
2021-12-14 09:37:05 +01:00
Jens Schauder
2c9975e8db After release cleanups.
See #3863
2021-11-12 10:38:57 +01:00
Jens Schauder
781ba63226 Prepare next development iteration.
See #3863
2021-11-12 10:38:54 +01:00
10 changed files with 117 additions and 43 deletions

View File

@@ -5,7 +5,7 @@
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.2.7</version>
<version>3.2.8</version>
<packaging>pom</packaging>
<name>Spring Data MongoDB</name>
@@ -15,7 +15,7 @@
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>2.5.7</version>
<version>2.5.8</version>
</parent>
<modules>
@@ -26,7 +26,7 @@
<properties>
<project.type>multi</project.type>
<dist.id>spring-data-mongodb</dist.id>
<springdata.commons>2.5.7</springdata.commons>
<springdata.commons>2.5.8</springdata.commons>
<mongo>4.2.3</mongo>
<mongo.reactivestreams>${mongo}</mongo.reactivestreams>
<jmh.version>1.19</jmh.version>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.2.7</version>
<version>3.2.8</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@@ -14,7 +14,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.2.7</version>
<version>3.2.8</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@@ -11,7 +11,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.2.7</version>
<version>3.2.8</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@@ -1803,8 +1803,9 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
Document projections = new Document();
Fields fields = context.getFields(type);
fields.forEach(it -> projections.append(it.getName(), 1));
return context.getMappedObject(projections, type);
fields.forEach(it -> projections.append(it.getTarget(), 1));
return projections;
}
}

View File

@@ -21,7 +21,7 @@ import java.util.ArrayList;
import java.util.List;
import org.bson.Document;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.DirectFieldReference;
@@ -122,13 +122,13 @@ public class TypeBasedAggregationOperationContext implements AggregationOperatio
return AggregationOperationContext.super.getFields(type);
}
List<String> fields = new ArrayList<>();
List<Field> fields = new ArrayList<>();
for (MongoPersistentProperty property : entity) {
fields.add(property.getName());
fields.add(Fields.field(property.getName(), property.getFieldName()));
}
return Fields.fields(fields.toArray(new String[0]));
return Fields.from(fields.toArray(new Field[0]));
}
/*
@@ -142,12 +142,13 @@ public class TypeBasedAggregationOperationContext implements AggregationOperatio
/**
* This toggle allows the {@link AggregationOperationContext context} to use any given field name without checking for
* its existence. Typically the {@link AggregationOperationContext} fails when referencing unknown fields, those that
* its existence. Typically, the {@link AggregationOperationContext} fails when referencing unknown fields, those that
* are not present in one of the previous stages or the input source, throughout the pipeline.
*
* @param type The domain type to map fields to.
* @return a more relaxed {@link AggregationOperationContext}.
* @since 3.1
* @see RelaxedTypeBasedAggregationOperationContext
*/
public AggregationOperationContext continueOnMissingFieldReference(Class<?> type) {
return new RelaxedTypeBasedAggregationOperationContext(type, mappingContext, mapper);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2021 the original author or authors.
* Copyright 2011-2022 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.
@@ -1388,6 +1388,14 @@ public class QueryMapper {
this.currentIndex = 0;
}
String nextToken() {
return pathParts.get(currentIndex + 1);
}
boolean hasNexToken() {
return pathParts.size() > currentIndex + 1;
}
/**
* Maps the property name while retaining potential positional operator {@literal $}.
*
@@ -1397,31 +1405,26 @@ public class QueryMapper {
protected String mapPropertyName(MongoPersistentProperty property) {
StringBuilder mappedName = new StringBuilder(PropertyToFieldNameConverter.INSTANCE.convert(property));
boolean inspect = iterator.hasNext();
while (inspect) {
String partial = iterator.next();
currentIndex++;
boolean isPositional = isPositionalParameter(partial) && property.isCollectionLike() ;
if(property.isMap() && currentPropertyRoot.equals(partial) && iterator.hasNext()){
partial = iterator.next();
currentIndex++;
}
if (isPositional || property.isMap() && !currentPropertyRoot.equals(partial)) {
mappedName.append(".").append(partial);
}
inspect = isPositional && iterator.hasNext();
if (!hasNexToken()) {
return mappedName.toString();
}
if(currentIndex + 1 < pathParts.size()) {
currentIndex++;
currentPropertyRoot = pathParts.get(currentIndex);
String nextToken = nextToken();
if (isPositionalParameter(nextToken)) {
mappedName.append(".").append(nextToken);
currentIndex += 2;
return mappedName.toString();
}
if (property.isMap()) {
mappedName.append(".").append(nextToken);
currentIndex += 2;
return mappedName.toString();
}
currentIndex++;
return mappedName.toString();
}

View File

@@ -27,6 +27,7 @@ import java.util.List;
import org.bson.Document;
import org.junit.jupiter.api.Test;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Cond;
import org.springframework.data.mongodb.core.aggregation.ProjectionOperationUnitTests.BookWithFieldAnnotation;
@@ -598,9 +599,31 @@ public class AggregationUnitTests {
assertThat(extractPipelineElement(target, 1, "$project")).isEqualTo(Document.parse(" { \"_id\" : \"$_id\" }"));
}
@Test // GH-3898
void shouldNotConvertIncludeExcludeValuesForProjectOperation() {
MongoMappingContext mappingContext = new MongoMappingContext();
RelaxedTypeBasedAggregationOperationContext context = new RelaxedTypeBasedAggregationOperationContext(WithRetypedIdField.class, mappingContext,
new QueryMapper(new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext)));
Document document = project(WithRetypedIdField.class).toDocument(context);
assertThat(document).isEqualTo(new Document("$project", new Document("_id", 1).append("renamed-field", 1)));
}
private Document extractPipelineElement(Document agg, int index, String operation) {
List<Document> pipeline = (List<Document>) agg.get("pipeline");
return (Document) pipeline.get(index).get(operation);
}
public class WithRetypedIdField {
@Id
@org.springframework.data.mongodb.core.mapping.Field
private String id;
@org.springframework.data.mongodb.core.mapping.Field("renamed-field")
private String foo;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* Copyright 2013-2022 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.
@@ -1208,7 +1208,7 @@ class UpdateMapperUnitTests {
Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
context.getPersistentEntity(EntityWithNestedMap.class));
assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("levelOne.a.b.d","e")));
assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set", new org.bson.Document("levelOne.a.b.d", "e")));
}
@Test // GH-3775
@@ -1218,7 +1218,7 @@ class UpdateMapperUnitTests {
Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
context.getPersistentEntity(EntityWithNestedMap.class));
assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("levelOne.0.1.3","4")));
assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set", new org.bson.Document("levelOne.0.1.3", "4")));
}
@Test // GH-3775
@@ -1228,7 +1228,7 @@ class UpdateMapperUnitTests {
Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
context.getPersistentEntity(EntityWithNestedMap.class));
assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("levelOne.0.1.c","4")));
assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set", new org.bson.Document("levelOne.0.1.c", "4")));
}
@Test // GH-3775
@@ -1238,7 +1238,7 @@ class UpdateMapperUnitTests {
Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
context.getPersistentEntity(EntityWithNestedMap.class));
assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("levelOne.0a.1b.3c","4")));
assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set", new org.bson.Document("levelOne.0a.1b.3c", "4")));
}
@Test // GH-3688
@@ -1251,6 +1251,36 @@ class UpdateMapperUnitTests {
assertThat(mappedUpdate).isEqualTo("{\"$set\": {\"intKeyedMap.1a.map.0b\": \"testing\"}}");
}
@Test // GH-3921
void mapNumericKeyInPathHavingComplexMapValyeTypes() {
Update update = new Update().set("testInnerData.testMap.1.intValue", "4");
Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
context.getPersistentEntity(TestData.class));
assertThat(mappedUpdate).isEqualTo("{ $set: { 'testInnerData.testMap.1.intValue': '4' }}");
}
@Test // GH-3921
void mapNumericKeyInPathNotMatchingExistingProperties() {
Update update = new Update().set("testInnerData.imaginaryMap.1.nonExistingProperty", "4");
Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
context.getPersistentEntity(TestData.class));
assertThat(mappedUpdate).isEqualTo("{ $set: { 'testInnerData.imaginaryMap.1.nonExistingProperty': '4' }}");
}
@Test // GH-3921
void mapNumericKeyInPathPartiallyMatchingExistingProperties() {
Update update = new Update().set("testInnerData.testMap.1.nonExistingProperty.2.someValue", "4");
Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
context.getPersistentEntity(TestData.class));
assertThat(mappedUpdate).isEqualTo("{ $set: { 'testInnerData.testMap.1.nonExistingProperty.2.someValue': '4' }}");
}
static class DomainTypeWrappingConcreteyTypeHavingListOfInterfaceTypeAttributes {
ListModelWrapper concreteTypeWithListAttributeOfInterfaceType;
}
@@ -1487,7 +1517,7 @@ class UpdateMapperUnitTests {
Map<Object, NestedDocument> concreteMap;
}
static class EntityWithIntKeyedMap{
static class EntityWithIntKeyedMap {
Map<Integer, EntityWithObjectMap> intKeyedMap;
}
@@ -1621,4 +1651,19 @@ class UpdateMapperUnitTests {
Map<String, Map<String, Map<String, Object>>> levelOne;
}
@Data
private static class TestData {
@Id private String id;
private TestInnerData testInnerData;
}
@Data
private static class TestInnerData {
private Map<Integer, TestValue> testMap;
}
@Data
private static class TestValue {
private int intValue;
}
}

View File

@@ -1,4 +1,4 @@
Spring Data MongoDB 3.2.7 (2021.0.7)
Spring Data MongoDB 3.2.8 (2021.0.8)
Copyright (c) [2010-2019] Pivotal Software, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -32,5 +32,6 @@ conditions of the subcomponent's license, as noted in the LICENSE file.