Skip to content

Commit

Permalink
merge #1150
Browse files Browse the repository at this point in the history
closes #1150
  • Loading branch information
evanchooly committed Jan 19, 2019
1 parent 9d3a592 commit e55e609
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,6 @@ public AggregationPipeline unwind(final String field, final UnwindOptions option
* @param projection the project to apply
* @return the DBObject
*/
@SuppressWarnings("unchecked")
private DBObject toDBObject(final Projection projection) {
String target;
if (firstStage) {
Expand All @@ -262,10 +261,22 @@ private DBObject toDBObject(final Projection projection) {
} else if (projection.getSource() != null) {
return new BasicDBObject(target, projection.getSource());
} else if (projection.getArguments() != null) {
DBObject args = toExpressionArgs(projection.getArguments());
if (target == null) {
return toExpressionArgs(projection.getArguments());
// Unwrap for single-argument expressions
if (args instanceof List<?> && ((List<?>) args).size() == 1) {
Object firstArg = ((List<?>) args).get(0);
if (firstArg instanceof DBObject) {
return (DBObject) firstArg;
}
}
return args;
} else {
return new BasicDBObject(target, toExpressionArgs(projection.getArguments()));
// Unwrap for single-argument expressions
if (args instanceof List<?> && ((List<?>) args).size() == 1) {
return new BasicDBObject(target, ((List<?>) args).get(0));
}
return new BasicDBObject(target, args);
}
} else {
return new BasicDBObject(target, projection.isSuppressed() ? 0 : 1);
Expand Down Expand Up @@ -312,7 +323,7 @@ private DBObject toExpressionArgs(final List<Object> args) {
result.add(arg);
}
}
return result.size() == 1 ? (DBObject) result.get(0) : result;
return result;
}

@Override
Expand Down
11 changes: 11 additions & 0 deletions morphia/src/main/java/xyz/morphia/aggregation/Projection.java
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,17 @@ public static Projection divide(final Object arg1, final Object arg2) {
return expression("$divide", arg1, arg2);
}

/**
* Counts and returns the total the number of items in an array
*
* @param expression The argument for $size can be any expression as long as it resolves to an array.
* @return the projection
* @mongodb.driver.manual reference/operator/aggregation/size $size
*/
public static Projection size(final Object expression) {
return expression("$size", expression);
}

/**
* Creates a modulo projection
*
Expand Down
27 changes: 27 additions & 0 deletions morphia/src/test/java/xyz/morphia/aggregation/AggregationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import static xyz.morphia.aggregation.Projection.divide;
import static xyz.morphia.aggregation.Projection.expression;
import static xyz.morphia.aggregation.Projection.projection;
import static xyz.morphia.aggregation.Projection.size;
import static xyz.morphia.geo.GeoJson.point;
import static xyz.morphia.query.Sort.ascending;

Expand Down Expand Up @@ -410,6 +411,32 @@ public void testProjection() {

}

@Test
public void testSizeProjection() {
getDs().save(asList(new Book("The Banquet", "Dante", 2),
new Book("Divine Comedy", "Dante", 1),
new Book("Eclogues", "Dante", 2),
new Book("The Odyssey", "Homer", 10),
new Book("Iliad", "Homer", 10)));

final AggregationPipeline pipeline = getDs().createAggregation(Book.class)
.group("author", grouping("titles", addToSet("title")))
.project(projection("_id").suppress(),
projection("author", "_id"),
projection("copies", size(projection("titles"))))
.sort(ascending("author"));
Iterator<Book> aggregate = pipeline.aggregate(Book.class);
Book book = aggregate.next();
Assert.assertEquals("Dante", book.author);
Assert.assertEquals(3, book.copies.intValue());

final List<DBObject> stages = ((AggregationPipelineImpl) pipeline).getStages();
Assert.assertEquals(stages.get(0), obj("$group", obj("_id", "$author").append("titles", obj("$addToSet", "$title"))));
Assert.assertEquals(stages.get(1), obj("$project", obj("_id", 0)
.append("author", "$_id")
.append("copies", obj("$size", "$titles"))));
}

@Test
public void testSkip() {
getDs().save(asList(new Book("The Banquet", "Dante", 2),
Expand Down

0 comments on commit e55e609

Please sign in to comment.