I'm quite new to MongoDB and its interaction with Java. I'm using this driver
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.4.2</version>
</dependency>
and I want to perform this aggregation query:
db.getCollection('COLLECTION').aggregate(
[
{"$match": {"val.elem.0001": {"$exists":true}}},
{"$project": {"FIELD_PATH": "$val.elem.0001"}},
{$group: {_id:{"FIELD": {"$literal": "0001"}},
"PATH": {"$addToSet": "$FIELD_PATH"}}}
]
);
The Java code I've written is the following, however I'm not sure if I correctly used the addToSet
method:
AggregateIterable<Document> output = collection.aggregate(Arrays.asList(
new Document("$match", new Document("val.elem.0001",new Document("$exists",true))),
new Document("$project", new Document("FIELD_PATH","$val.elem.0001")),
new Document("$group", new Document("_id",new Document("FIELD", new Document("$literal", "0001"))
.append("PATH", Accumulators.addToSet("$PATH", "$FIELD_PATH"))))));
It is correct? Because I can't print the result on screen if I add the "append" part. The error that returns is
Can't find a codec for class com.mongodb.client.model.BsonField
.
So, to summarize and make more readable and comprehensive what I've asked:
Your usage of the API is incorrect.
Change your aggregation to the one below (stick with Document
for expressions).
AggregateIterable<Document> output = collection.aggregate(Arrays.asList(
new Document("$match", new Document("val.elem.0001", new Document("$exists", true))),
new Document("$project", new Document("FIELD_PATH", "$val.elem.0001")),
new Document("$group", new Document("_id", new Document("FIELD", new Document("$literal", "0001"))).append("PATH", new Document("$addToSet", "$FIELD_PATH")))));
BsonField
is a helper class primarily built to providea data holder for Accumulators
which return key
and Bson
value pair. So it is not meant to be used as value type. When used with helper methods, it is converted into Document
and serialized using the document codec.
You can rework your aggregation to use helper methods (Filters
, Projections
Accumulators
& Aggregates
).
AggregateIterable<Document> output = collection.aggregate(Arrays.asList(
Aggregates.match(Filters.exists("val.elem.0001")),
Aggregates.project(Projections.computed("FIELD_PATH", "$val.elem.0001")),
Aggregates.group( new Document("FIELD", new Document("$literal", "0001")), Accumulators.addToSet("PATH", "$FIELD_PATH"))));
You can further simplify the aggregation by using static imports.
import static com.mongodb.client.model.Accumulators.addToSet;
import static com.mongodb.client.model.Aggregates.group;
import static com.mongodb.client.model.Aggregates.match;
import static com.mongodb.client.model.Aggregates.project;
import static com.mongodb.client.model.Projections.computed;
import static java.util.Arrays.*;
AggregateIterable<Document> output = collection.aggregate(asList(
match(Filters.exists("val.elem.0001")),
project(computed("FIELD_PATH", "$val.elem.0001")),
group( new Document("FIELD", new Document("$literal", "0001")), addToSet("PATH", "$FIELD_PATH"))));
See the documentation for more information.