i have following bson data in mongoDB
{name : "c1"
arr : [
{
partyName : "p1",
poNumber : "789",
},
{
partyName : "p1",
poNumber : "700",
},
{
partyName : "p3",
poNumber : "889",
}
]
},
{name : "c2"
arr : [
{
partyName : "p1",
poNumber : "789",
},
{
partyName : "p2",
poNumber : "700",
},
{
partyName : "p3",
poNumber : "889",
}
]
}
i want all unique values of partyName of name: "c1" object like [p1,p3]. i tried this
const unique = await User.distinct({name :"c1","createPurchaseOrder.partyName"})
(note :- User is my schema name ) but it gives error, i tried to search on web but cant find solution please help me with this
CodePudding user response:
One option is using $reduce
:
db.collection.aggregate([
{$match: {name: "c1"}},
{$project: {
res: {
$reduce: {
input: "$arr",
initialValue: [],
in: {$setUnion: ["$$value", ["$$this.partyName"]]}
}
}
}
}
])
See how it works on the playground example
CodePudding user response:
Query1
- match for the document with
name=c1
- path to take the array with the
partyName
and union with the empty array to remove the duplicates - union => order can be lost in
patyNames
aggregate(
[{"$match": {"name": {"$eq": "c1"}}},
{"$project":
{"_id": 0, "parties-unique": {"$setUnion": ["$arr.partyName", []]}}}])
Query2
- the above is fast and simple but loses the order of the names
- if you want to keep the original order, you can use this instead
- reduce and add on array only if element doesn't already exists
aggregate(
[{"$match": {"name": {"$eq": "c1"}}},
{"$set":
{"parties-unique":
{"$reduce":
{"input": "$arr.partyName",
"initialValue": [],
"in":
{"$cond":
[{"$in": ["$$this", "$$value"]}, "$$value",
{"$concatArrays": ["$$value", ["$$this"]]}]}}}}}])