Reputation: 367
I'm trying to use $addToSet to add multiple objects to a single array when aggregating in Mongo.
The format of the data may not be the best but I don't have the ability to change it. Here is an example of the kinds of documents I'm querying:
{
"question" : "How tall is the CN Tower?",
"answer" : "553.3 metres",
"user": "user_1"
"information" : {
"info_details" : {
"info_1" : {
"score" : 23,
"size" : 855,
"total" : 29,
},
"info_2" : {
"score" : 1234,
"size" : 1000,
"total" : 3,
"index" : "index_1",
"rank" : 1
}
}
}
}
Below is a sample query ($project section omitted). Though the double $addToSet doesn't work, I put it there as it shows what I want to accomplish logically. Note that the two info objects may have different fields and values.
...{
"$group": {
"_id": {
"question": "$doc.questionId",
"answer": "$doc.answerCandidateId",
"user": "$doc.user"
},
"info": {
"$addToSet": {
"score": "$doc.information.info_details.info_1.score",
"size": "$doc.information.info_details.info_1.size",
"total": "$doc.information.info_details.info_1.total"
},
// This second addToSet overwrites the first info value (does not work as I want it to)
"info": {
"$addToSet": {
"score": "$doc.information.info_details.info_2.score",
"size": "$doc.information.info_details.info_2.size",
"total": "$doc.information.info_details.info_2.total",
"index": "$doc.information.info_details.info_2.index",
"rank": "$doc.information.info_details.info_2.rank"
}
}
}
}
}
My goal is to have an "info" set with all the info objects (minus duplicates) from the $group operation.
{
"question": "question_1",
"answer": "answer_1",
"user": "user_1",
"info": [ {"score": 23, "size": 855, "total": 29}, {"score": 1234, "size": 1000, "total": 3, "index": "index_1", "rank": 1}]
}
Is there a way I can add multiple objects within a $group operation to the same set?
Upvotes: 5
Views: 13082
Reputation: 75914
You can try below solutions based on mongo version.
The idea here is to change the dynamic keys into labeled key value structure i.e. change embedded doc info_1
& info_2
into embedded arrays and followed by $unwind
& $group
.
Mongo Version 3.4
You can use $objectToArrays
operator to convert embedded documents into embedded arrays.
db.collection.aggregate({
$addFields: {
information: {
$objectToArray: "$information.info_details"
}
}
}, {
$unwind: "$information"
}, {
$group: {
_id: {
question: "$question",
answer: "$answer",
user: "$user"
},
info: {
$addToSet: "$information.v"
}
}
})
Mongo Version 3.2
You can use []
brackets to do something similar to convert embedded documents into embedded arrays.
db.collection.aggregate({
$project: {
question: 1,
answer: 1,
user: 1,
information: ["$information.info_details.info_1", "$information.info_details.info_2"]
}
}, {
$unwind: "$information"
}, {
$group: {
_id: {
question: "$question",
answer: "$answer",
user: "$user"
},
info: {
$addToSet: "$information"
}
}
})
Upvotes: 7