'How do I use Spring Mongo to group two fields and get a array of one fields based on the other?
Let me give a example here:
Two entries in the collection Author:
{
"name" : "Joe"
"Book" : "A"
},
{
"name" : "Joe"
"Book" : "B"
}
Now, if I use the aggregation function in Mongo via spring mongo, basically just to grab the books with name Joe, it could be coded like:
Aggregation agg = newAggregation(Map.class, group("name", "Book"));
AggregationResults<Map> results = mongoTemplate.aggregate(agg, "Author",
Map.class);
Obviously I could get two Maps this way, one has entry {"name":"Joe", "Book": A}
, the other has {"name" : "Joe", "Book" : "B"}
But what if I want get ONLY one result back, with one entry :
{"name" : Joe, "Books" : ["A", "B"]}?
I'm not sure if it is reachable just using one query. It certainly could be achieved by multiple steps, which I'd hate to do..
Solution 1:[1]
You need to use the $addToSet
operator in your $group
pipeline. This will return an array of all unique values ["A", "B"]
that results from applying the $group
expression to each document in a group of documents that share the same group by key "name"
. So in mongo shell you have
db.author.aggregate([
{ $group: {
_id: '$name',
Books: { $addToSet: '$Book' }
} }
]);
which brings back the desired result
{
"result" : [
{
"_id" : "Joe",
"Books" : [ "B", "A" ]
}
],
"ok" : 1
}
The equivalent Spring aggregation:
Aggregation agg = newAggregation(Map.class, group("name").addToSet("Book").as("Books"));
AggregationResults<Map> results = mongoTemplate.aggregate(agg, "Author", Map.class);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |