Skip to content

Commit 6b2111c

Browse files
committed
Add KeyFunction support to group in DBCollection
JAVA-1979
1 parent 2ffdcf5 commit 6b2111c

File tree

2 files changed

+61
-2
lines changed

2 files changed

+61
-2
lines changed

driver/src/main/com/mongodb/GroupCommand.java

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import org.bson.BsonDocumentWrapper;
2121
import org.bson.BsonJavaScript;
2222

23+
import static com.mongodb.assertions.Assertions.notNull;
24+
2325
/**
2426
* This class groups the argument for a group operation and can build the underlying command object
2527
*
@@ -28,6 +30,7 @@
2830
public class GroupCommand {
2931
private final String collectionName;
3032
private final DBObject keys;
33+
private final String keyf;
3134
private final DBObject condition;
3235
private final DBObject initial;
3336
private final String reduce;
@@ -45,12 +48,38 @@ public class GroupCommand {
4548
*/
4649
public GroupCommand(final DBCollection collection, final DBObject keys, final DBObject condition,
4750
final DBObject initial, final String reduce, final String finalize) {
51+
notNull("collection", collection);
4852
this.collectionName = collection.getName();
4953
this.keys = keys;
5054
this.condition = condition;
5155
this.initial = initial;
5256
this.reduce = reduce;
5357
this.finalize = finalize;
58+
this.keyf = null;
59+
}
60+
61+
/**
62+
* Creates a new group command.
63+
*
64+
* @param collection the collection from which to perform the group by operation.
65+
* @param keyf the function that creates a "key object" for use as the grouping key
66+
* @param condition optional - a filter to determine which documents in the collection to process.
67+
* @param initial the initial state of the aggregation result document.
68+
* @param reduce a JavaScript aggregation function that operates on the documents during the grouping operation.
69+
* @param finalize optional - a JavaScript function that runs each item in the result set before group returns the final value.
70+
*
71+
* @since 3.1
72+
*/
73+
public GroupCommand(final DBCollection collection, final String keyf, final DBObject condition,
74+
final DBObject initial, final String reduce, final String finalize) {
75+
notNull("collection", collection);
76+
this.collectionName = collection.getName();
77+
this.keyf = notNull("keyf", keyf);
78+
this.condition = condition;
79+
this.initial = initial;
80+
this.reduce = reduce;
81+
this.finalize = finalize;
82+
this.keys = null;
5483
}
5584

5685
/**
@@ -59,10 +88,18 @@ public GroupCommand(final DBCollection collection, final DBObject keys, final DB
5988
* @return a DBObject containing the group command as a MongoDB document
6089
*/
6190
public DBObject toDBObject() {
62-
DBObject args = new BasicDBObject("ns", collectionName).append("key", keys)
63-
.append("cond", condition)
91+
DBObject args = new BasicDBObject("ns", collectionName).append("cond", condition)
6492
.append("$reduce", reduce)
6593
.append("initial", initial);
94+
95+
if (keys != null) {
96+
args.put("key", keys);
97+
}
98+
99+
if (keyf != null) {
100+
args.put("$keyf", keyf);
101+
}
102+
66103
if (finalize != null) {
67104
args.put("finalize", finalize);
68105
}
@@ -86,6 +123,10 @@ GroupOperation<DBObject> toOperation(final MongoNamespace namespace, final DBObj
86123
operation.key(new BsonDocumentWrapper<DBObject>(keys, codec));
87124
}
88125

126+
if (keyf != null) {
127+
operation.keyFunction(new BsonJavaScript(keyf));
128+
}
129+
89130
if (condition != null) {
90131
operation.filter(new BsonDocumentWrapper<DBObject>(condition, codec));
91132
}

driver/src/test/functional/com/mongodb/DBCollectionFunctionalSpecification.groovy

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,24 @@ class DBCollectionFunctionalSpecification extends FunctionalSpecification {
387387
that result, contains(~['x': 'a', 'count': 3.0D], ~['x': 'b', 'count': 4.0D], ~['x': 'c', 'count': 1.0D]);
388388
}
389389

390+
def 'should group using a key function in a GroupCommand'() {
391+
given:
392+
insertDataForGroupTests()
393+
GroupCommand command = new GroupCommand(collection,
394+
'function(doc){ return {x: doc.x} }',
395+
null,
396+
~['count': 0],
397+
'function(o , p){ p.count++; }',
398+
null);
399+
400+
when:
401+
DBObject result = collection.group(command);
402+
403+
then:
404+
result.size() == 3
405+
that result, contains(~['x': 'a', 'count': 3.0D], ~['x': 'b', 'count': 4.0D], ~['x': 'c', 'count': 1.0D]);
406+
}
407+
390408
def 'should group and count only those documents that fulfull the given condition'() {
391409
given:
392410
insertDataForGroupTests()

0 commit comments

Comments
 (0)