'MongoDB - How to filter document objects within array?

I have a problem with filtering fields(objects) from my document using find function.

Here is my db.collection.find(..) document:

{
  "_id": BinData(3, "Uz+QwtoVMt7hjpqMrLxVhQ=="),
  "name": "jeorge",
  "permissions": [
    {
      "key": "group.staff",
      "value": true,
      "context": [
        { "key": "server", "value": "test" }
      ]
    },
    {
      "key": "group.tester",
      "value": true,
      "context": [
        { "key": "server", "value": "test" }
      ]
    },
    {
      "key": "test.test",
      "value": true
    },
    {
      "key": "group.default",
      "value": true
    },
    {
      "key": "group.helper",
      "value": true
    }
  ]
}

How can I filter my document in two ways?

a) Display only fields with nested context object.

b) Display only fields, which hasn't got nested context objects.

Also I need to check if parent's object property key contains string "group" as value (If not - skip it).

For situation b, I have tried this function, but it prints result with only the first matched element (based on mongodb's documentation).

db.collection.find(
{
    "_id": BinData(3, "Uz+QwtoVMt7hjpqMrLxVhQ==")
},
{
    "permissions": {
        $elemMatch: {
            "key": {
                $regex: "group",
            },
            "value": true
        }
    }
}
);

Is it possible by single query? Thanks!



Solution 1:[1]

db.collection.aggregate([
  {
    $match: { _id: BinData(3, "Uz+QwtoVMt7hjpqMrLxVhQ==") }
  },
  {
    $set: {
      permissions: {
        $filter: {
          input: "$permissions",
          as: "p",
          cond: {
            $and: [
              "$$p.context",
              { $regexMatch: { input: "$$p.key", regex: "group" } }
            ]
          }
        }
      }
    }
  }
])

mongoplayground


db.collection.aggregate([
  {
    $match: {
      _id: BinData(3, "Uz+QwtoVMt7hjpqMrLxVhQ==")
    }
  },
  {
    $set: {
      permissions: {
        $filter: {
          input: "$permissions",
          as: "p",
          cond: {
            $and: [
              {
                $not: [ "$$p.context" ]
              },
              {
                $regexMatch: {
                  input: "$$p.key",
                  regex: "group"
                }
              }
            ]
          }
        }
      }
    }
  }
])

mongoplayground

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1