Reputation: 30300
I have a MongoDB collection with a particular field , call it target
, that looks like this:
{ "a": 123, "target": 1 }
{ "a": 456, "target": 2 }
{ "a": 324, "target": 3 }
{ "a": 333, "target": 1 }
{ "a": 678, "target": 1 }
{ "a": 789, "target": 2 }
{ "a": 555, "target": 3 }
I would like to know if there is a way to accomplish the following conceptually (if not necessarily literally):
[
{ "target": 1, [{ "a": 123, "target": 1 }, { "a": 333, "target": 1 }, { "a": 678, "target": 1 }] },
{ "target": 2, [{ "a": 456, "target": 2 }, { "a": 789, "target": 2 }] },
{ "target": 3, [{ "a": 324, "target": 3 }, { "a": 555, "target": 3 }] }
]
Basically, I would like a mapping of target
values to all the documents containing those target values, but reading and re-reading the documentation hasn't helped me figure out how to do this with the aggregation framework or anything else. I would like to know if this is possible before I set about doing this in my application code.
Upvotes: 0
Views: 46
Reputation: 3510
AFAIK, it won't be possible to create a "single array" that contains all the results; however what you can do is to create a document for each group (target) as described below.
You will be able to achieve this by doing a $push in your group
db.collection.aggregate([
{$group : { "_id" : "$target" , "values" :{ $push: { a : "$a" , target : "$target" } } } },
{$project : { "_id" : 0 , "values" : 1, "target" : "$_id" , } }
]);
the result will be something like :
{
"values": [
{
"a": 324,
"target": 3
},
{
"a": 555,
"target": 3
}
],
"target": 3
}{
"values": [
{
"a": 456,
"target": 2
},
{
"a": 789,
"target": 2
}
],
"target": 2
}{
"values": [
{
"a": 123,
"target": 1
},
{
"a": 333,
"target": 1
},
{
"a": 678,
"target": 1
}
],
"target": 1
}
As you can see, I have added a name to the array "values" since your result example is not a valid JSON document
You can also add the $out step that will save the result of this aggregation in a new collection
But you have to be very careful with such aggregation, since you are building an array in your results: keep in mind that a document could not be bigger than 16Mb. So if you have "too" many entries for a target you may reach this limit.
Upvotes: 2
Reputation: 7840
Hi as per your question I found some way you can achieve this it not exactly what you expected but it matches your criteria below aggregation may help you
db.collectionName.aggregate([
{
"$group": {
"_id": {
"a": "$a",
"target": "$target"
}
}
},
{
"$group": {
"_id": "$_id.target",
"targetData": {
"$push": {
"a": "$_id.a",
"target": "$_id.target"
}
}
}
}
])
Upvotes: 1