Home > other >  How can I do a intersection betwen several arrays?
How can I do a intersection betwen several arrays?

Time:10-11

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?.

  1. $unwind: Deconstruct students array field to output documents for each element.
  2. group: Group multiple documents to get initialStudent ($first).
  3. $set: Create new field common. With $reduce operator to flatten the array for $setIntersection start from initialStudent and every next element in $students.
  4. $project: Display student field with a nested array for the result of common 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"
      ]
    }
  }
])

Sample Mongo Playground


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));
  • Related