Hello I am retrieving the following data
[
{
"_id": null,
"count": 2,
"students": [
[
"a",
"b"
],
[
"a",
"c",
"d"
]
]
}
]
Using this querie:
aggregate([
{
$match: {
class: {
$in: classes,
},
},
},
{
$project: { students: 1 },
},
{
$group: {
_id: null,
count: { $sum: 1 },
data: { $push: "$students" },
},
},
{
$project: {
count: 1,
students: {
$setIntersection: "$data",
},
},
},
])
But the idea is that students become at an intersection of that arrays in order to get only
[
{
"_id": null,
"count": 2,
"students": [
[
"a",
],
]
}
]
I tried several combinations of use setIntersection but any of that worked.
How can get only that intersection?
Thanks
CodePudding user response:
The multiple arrays intersection concept is similar to chridam's answer on How to find set intersection of sets between the documents in a single collection in MongoDB?.
$unwind
: Deconstructstudents
array field to output documents for each element.group
: Group multiple documents to getinitialStudent
($first
).$set
: Create new fieldcommon
. With$reduce
operator to flatten the array for$setIntersection
start frominitialStudent
and every next element in$students
.$project
: Displaystudent
field with a nested array for the result ofcommon
in (3).
db.collection.aggregate([
{
"$unwind": "$students"
},
{
"$group": {
"_id": 0,
count: {
$sum: 1
},
"students": {
"$push": "$students"
},
"initialStudent": {
"$first": "$students"
}
}
},
{
"$set": {
"common": {
"$reduce": {
"input": "$students",
"initialValue": "$initialStudent",
"in": {
"$setIntersection": [
"$$value",
"$$this"
]
}
}
},
}
},
{
$project: {
"count": 1,
"students": [
"$common"
]
}
}
])
Improvement
Appreciate and credit @varman's suggestion on the query,
Pipelines 1 ($unwind
) & 2 ($group
) for the above solution can be simplified into $set
pipeline to retrieve $first
and $count
for students
.
{
$addFields: {
"initialStudent": {
"$first": "$students"
},
"count": {
"$size": "$students"
}
}
}
CodePudding user response:
One approach could be to do the intersection after getting the data.
//assuming students has only two arrays.
const IntersectedArray = students[0].filter(value => students[1].includes(value));