Reputation: 1335
I'm looking to retrieve all values of my collection in a single set :
Example :
` "_id" : {
"origin" : "xx",
"destination" : "yy"
},
"paths" : [
[
"tt"
]
]
}
/* 2 */
{
"_id" : {
"origin" : "aa",
"destination" : "bb"
},
"paths" : [
[
"cc"
]
]
}
/* 3 */
{
"_id" : {
"origin" : "xy",
"destination" : "yx"
},
"paths" : [
[
"yy",
"tt",
"cc"
]
]
}`
Expected output :
Nodes : {"xx", "yy", "aa", "bb","xy", "yx"}
I tried $setUnion
but it doesn't work because I have string
$addToset
is impossible to add both fields : "origin" and "destination"
How to retrieve all values of my collection's fields (id.origin and id.destination) to a set?
Thank you
Upvotes: 0
Views: 81
Reputation: 8988
Since this is very special case where you want custom formatting, your best bet will be map-reduce feature of MongoDB. However, this formatting can be achieved with help of aggregation framework too. I'm adding both solutions.
Aggregation framework:
db.collection.aggregate([
{
$group:{
_id:null,
origin:{
$addToSet:"$_id.origin"
},
destination:{
$addToSet:"$_id.destination"
}
}},
{
$project:{
_id:0,
Nodes:{
$setUnion:["$origin","$destination"]
}
}}
])
Output:
{
"Nodes" : [
"yy",
"yx",
"xx",
"bb",
"aa",
"xy"
]
}
Map Reduce:
db.collection.mapReduce(
function () {
emit(1, this._id);
},
function (key, values) {
var o = {};
o.Nodes = [];
for (var i = 0; i < values.length; i++) {
o.Nodes.push(values[i].origin);
o.Nodes.push(values[i].destination);
}
return o;
},
{
out: { inline: 1 }
});
Output:
{
"results" : [
{
"_id" : NumberInt(1),
"value" : {
"Nodes" : [
"xx",
"yy",
"aa",
"bb",
"xy",
"yx"
]
}
}
],
"timeMillis" : NumberInt(22),
"counts" : {
"input" : NumberInt(3),
"emit" : NumberInt(3),
"reduce" : NumberInt(1),
"output" : NumberInt(1)
},
"ok" : NumberInt(1)
}
results.values.Nodes
contains your desired result.
Upvotes: 2
Reputation: 2777
In the aggregation pipeline first you can have two sets (Originset and DestinationSet) and after that you can use setUnion to have the union set of the two set.
Upvotes: 1