i have this array, i want to merge all elements inside the objects in the nested arrays and remove the duplicates.. the array is the output of mongo db populate so answers from there or just js will be amazing :)
"visitors": [
[
{
"name": "matan",
"id": "61793e6a0e08cdcaf213c0b1"
},
{
"name": "shani",
"id": "61793e910e08cdcaf213c0b5"
}
],
[
{
"name": "david",
"id": "6179869cb4944c6b19b05a23"
},
{
"name": "orit",
"id": "617986e535fdf4942ef659bd"
}
],
[
{
"name": "david",
"id": "6179869cb4944c6b19b05a23"
},
{
"name": "orit",
"id": "617986e535fdf4942ef659bd"
}
]
]
would like this output -
"visitors": [
{
"name": "matan",
"id": "61793e6a0e08cdcaf213c0b1"
},
{
"name": "shani",
"id": "61793e910e08cdcaf213c0b5"
},
{
"name": "david",
"id": "6179869cb4944c6b19b05a23"
},
{
"name": "orit",
"id": "617986e535fdf4942ef659bd"
},
]
these are my collections i need to get all visitors on one solar system, so > solars > planets > visitors
const solarsModel = new Schema({
planets: [ { type: Schema.Types.ObjectId ,ref:'planet'} ],
starName: { type: String, required: true, default: "" }
})
const planetModel = new Schema({
planetName: { type: String, required: true, default: "" },
system:{type: Schema.Types.ObjectId, ref: 'solar'},
visitors: [{ type: Schema.Types.ObjectId , ref: 'visitor'}]
})
const visitorModel = new Schema({
visitorName:{ type: String, required: true, default: "" },
homePlanet: {type: Schema.Types.ObjectId, ref:"planet" },
visitedPlanets: [{ type: Schema.Types.ObjectId, ref:"planet" }]
})
this is what i did to achieve a result would love to use Aggregate..
const response = await solarModel
.findById({ _id: data.id })
.select({ starName: 1, _id: 0 })
.populate({
path: "planets",
select: { visitors: 1, _id: 0 },
populate: {
path: "visitors",
select: "visitorName",
},
})
.exec();
visitors = visitors.flat();
Which gives us this:
[
{ name: 'matan', id: '61793e6a0e08cdcaf213c0b1' },
{ name: 'shani', id: '61793e910e08cdcaf213c0b5' },
{ name: 'david', id: '6179869cb4944c6b19b05a23' },
{ name: 'orit', id: '617986e535fdf4942ef659bd' },
{ name: 'david', id: '6179869cb4944c6b19b05a23' },
{ name: 'orit', id: '617986e535fdf4942ef659bd' }
]
let uniqueIds= [...new Set(visitors.map(v => v.id)]
Which gives us this:
[
'61793e6a0e08cdcaf213c0b1',
'61793e910e08cdcaf213c0b5',
'6179869cb4944c6b19b05a23',
'617986e535fdf4942ef659bd'
]
visitors = uniqueIds.map(id => {
let name = visitors.find(v => v.id === id).name;
return {
id,
name
}
});
Which gives us this:
[
{ name: 'matan', id: '61793e6a0e08cdcaf213c0b1' },
{ name: 'shani', id: '61793e910e08cdcaf213c0b5' },
{ name: 'david', id: '6179869cb4944c6b19b05a23' },
{ name: 'orit', id: '617986e535fdf4942ef659bd' },
]
You can use aggregate()
like this:
$unwind
twice due to nested array$group
using $addToSet
to not get duplicates. db.collection.aggregate([
{
"$unwind": "$visitors"
},
{
"$unwind": "$visitors"
},
{
"$group": {
"_id": null,
"visitors": {
"$addToSet": {
"id": "$visitors.id",
"name": "$visitors.name"
}
}
}
}
])
Example here
Query
*try it on your driver, playground has a problem with field orders sometimes it loses it, here we compare documents to remove the duplicates.
aggregate(
[{"$set":
{"visitors":
{"$setUnion":
[{"$reduce":
{"input": "$visitors",
"initialValue": [],
"in": {"$concatArrays": ["$$value", "$$this"]}}},
[]]}}}])
Results
[{
"visitors": [
{
"name": "david",
"id": "6179869cb4944c6b19b05a23"
},
{
"name": "matan",
"id": "61793e6a0e08cdcaf213c0b1"
},
{
"name": "orit",
"id": "617986e535fdf4942ef659bd"
},
{
"name": "shani",
"id": "61793e910e08cdcaf213c0b5"
}
]
}]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.