DATAMONGO-788 - Projection operations do not render synthetic fields properly.

Introduced boolean isSynthetic() attribute to FieldReference to determine if the given reference points to a synthetic field, as this controls whether we render a simple include (1) or a concrete reference ($fieldName) E.g. isSynthetic() would be true for a field reference to _id.

Original pull request: #90.
This commit is contained in:
Thomas Darimont
2013-10-31 14:16:49 +00:00
committed by Oliver Gierke
parent 49af31bb6e
commit 8b3da2d7f9
4 changed files with 83 additions and 1 deletions

View File

@@ -334,6 +334,13 @@ public class ExposedFields implements Iterable<ExposedField> {
this.field = field;
}
/**
* @return
*/
public boolean isSynthetic() {
return field.synthetic;
}
/**
* Returns the raw, unqualified reference, i.e. the field reference without a {@literal $} prefix.
*

View File

@@ -508,7 +508,7 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
// check whether referenced field exists in the context
FieldReference reference = context.getReference(field.getTarget());
if (field.getName().equals(field.getTarget())) {
if (field.getName().equals(field.getTarget()) && reference.isSynthetic()) {
// render field as included
return 1;

View File

@@ -85,6 +85,7 @@ public class AggregationTests {
mongoTemplate.dropCollection(Product.class);
mongoTemplate.dropCollection(UserWithLikes.class);
mongoTemplate.dropCollection(DATAMONGO753.class);
mongoTemplate.dropCollection(DATAMONGO788.class);
}
/**
@@ -520,6 +521,36 @@ public class AggregationTests {
}
}
/**
* @see DATAMONGO-788
*/
@Test
public void referencesToGroupIdsShouldBeRenderedProperly() {
mongoTemplate.insert(new DATAMONGO788(1, 1));
mongoTemplate.insert(new DATAMONGO788(1, 1));
mongoTemplate.insert(new DATAMONGO788(1, 1));
mongoTemplate.insert(new DATAMONGO788(2, 1));
mongoTemplate.insert(new DATAMONGO788(2, 1));
AggregationOperation projectFirst = Aggregation.project("x", "y").and("xField").as("x").and("yField").as("y");
AggregationOperation group = Aggregation.group("x", "y").count().as("xPerY");
AggregationOperation project = Aggregation.project("xPerY", "x", "y").andExclude("_id");
TypedAggregation<DATAMONGO788> aggregation = Aggregation.newAggregation(DATAMONGO788.class, projectFirst, group,
project);
AggregationResults<DBObject> aggResults = mongoTemplate.aggregate(aggregation, DBObject.class);
List<DBObject> items = aggResults.getMappedResults();
assertThat(items.size(), is(2));
assertThat((Integer) items.get(0).get("xPerY"), is(2));
assertThat((Integer) items.get(0).get("x"), is(2));
assertThat((Integer) items.get(0).get("y"), is(1));
assertThat((Integer) items.get(1).get("xPerY"), is(3));
assertThat((Integer) items.get(1).get("x"), is(1));
assertThat((Integer) items.get(1).get("y"), is(1));
}
private void assertLikeStats(LikeStats like, String id, long count) {
assertThat(like, is(notNullValue()));
@@ -585,4 +616,22 @@ public class AggregationTests {
this.up = up;
}
}
static class DATAMONGO788 {
int x;
int y;
int xField;
int yField;
public DATAMONGO788() {}
public DATAMONGO788(int x, int y) {
this.x = x;
this.xField = x;
this.y = y;
this.yField = y;
}
}
}

View File

@@ -15,12 +15,19 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import java.util.List;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.data.mongodb.core.DBObjectUtils;
import com.mongodb.DBObject;
/**
* Unit tests for {@link Aggregation}.
@@ -94,4 +101,23 @@ public class AggregationUnitTests {
project("a", "b") // b should still be available
).toDbObject("foo", Aggregation.DEFAULT_CONTEXT);
}
/**
* @see DATAMONGO-788
*/
@Test
public void referencesToGroupIdsShouldBeRenderedAsReferences() {
DBObject agg = newAggregation( //
project("a"), //
group("a").count().as("aCnt"), //
project("aCnt", "a") //
).toDbObject("foo", Aggregation.DEFAULT_CONTEXT);
@SuppressWarnings("unchecked")
DBObject secondProjection = ((List<DBObject>) agg.get("pipeline")).get(2);
DBObject fields = DBObjectUtils.getAsDBObject(secondProjection, "$project");
assertThat((Integer) fields.get("aCnt"), is(1));
assertThat((String) fields.get("a"), is("$_id.a"));
}
}