Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mongo $filter and multiple condition in sub-sub array

I have this portion of collections:

[{
  "_id": ObjectId("604f3ae3194f2135b0ade569"),
  "parameters": [
    {
      "_id": ObjectId("602b7455f4b4bf5b41662ec1"),
      "name": "Purpose",
      "options": [
        {
          "id": ObjectId("602b764ff4b4bf5b41662ec2"),
          "name": "debug",
          "sel": true
        },
        {
          "id": ObjectId("602b767df4b4bf5b41662ec3"),
          "name": "performance",
          "sel": false
        },
        {
          "id": ObjectId("602b764ff4b4bf5b41662ec4"),
          "name": "security",
          "sel": true
        },
        {
          "id": ObjectId("602b767df4b4bf5b41662ec5"),
          "name": "Not Applicable",
          "sel": false
        }
      ],
      "type": "multiple"
    }]
}]

And this query:

db.testCollection.aggregate([
    { $unwind: "$parameters" },
    {
        $match: {
            "parameters._id": ObjectId("602b7455f4b4bf5b41662ec1"),
        }
    },
    {
        $addFields: {
            match: {
                $filter: {
                    input: "$parameters.options",
                    as: "option",
                    cond: {
                        $and: [
                           { $eq: ["$$option.id", ObjectId('602b764ff4b4bf5b41662ec2')] },
                           { $eq: ["$$option.sel", true] }
                        ]
                    }
                }
            }
        }
    }
])

The result is a new array match with, in this case,

"match": [
      {
        "id": ObjectId("602b764ff4b4bf5b41662ec2"),
        "name": "debug",
        "sel": true
      }
    ]

How I can match, for collections, match for example

"id": ObjectId("602b764ff4b4bf5b41662ec2") and 
"id": ObjectId("602b764ff4b4bf5b41662ec4")

and have a result array with or two results or empty?

like image 722
Francesco Avatar asked Aug 07 '26 11:08

Francesco


1 Answers

I am not sure it is possible in single condition inside $filter, but you can try with $let,

  • $let to declare a variable called filtered and store your filtered result
  • $in to check condition if filtered element size is 2 then return filtered result otherwise blank array
  • You have to put the number that you are matching number of ids in filter in $eq condition
  {
    $addFields: {
      match: {
        $let: {
          vars: {
            filtered: {
              $filter: {
                input: "$parameters.options",
                as: "option",
                cond: {
                  $and: [
                    {
                      $in: [
                        "$$option.id",
                        [ObjectId("602b764ff4b4bf5b41662ec2"), ObjectId("602b767df4b4bf5b41662ec3")]
                      ]
                    },
                    { $eq: ["$$option.sel", true] }
                  ]
                }
              }
            }
          },
          in: {
            $cond: [
              { $eq: [{ $size: "$$filtered" }, 2] },
              "$$filtered",
              []
            ]
          }
        }
      }
    }
  }

Playground

like image 80
turivishal Avatar answered Aug 10 '26 12:08

turivishal