MongoDB 聚合:如何判断一个数组是否包含多个元素

MongoDB aggregation: how to find out if an array contains multiple elements

我有以下数据。

[
  {
    "_id": 1,
    "array": [
      {
        "name": "name1",
        "nestedArray": [
          {
            "key": "key1",
            "value": "value1"
          },
          {
            "key": "key2",
            "value": "value2"
          }
        ]
      },
      {
        "name": "name2",
        "nestedArray": [
          {
            "key": "key1",
            "value": "abc"
          },
          {
            "key": "key2",
            "value": "value2"
          }
        ]
      }
    ]
  }
]

playground 我想保留其 nestedArray 包含 2 个匹配元素的条目并删除其他元素。 2个元素如下

{
    "key": "key1",
    "value": "abc"
},
{
    "key": "key2",
    "value": "value2"
}

所以结果会低于

[
  {
    "_id": 1,
    "array": [
      {
        "name": "name2",
        "nestedArray": [
          {
            "key": "key1",
            "value": "abc"
          },
          {
            "key": "key2",
            "value": "value2"
          }
        ]
      }
    ]
  }
]

删除了 name="name1" 的那个,因为它只有一个匹配元素。 感觉我们可以使用 $elemMatch 但无法弄清楚。

您并没有真正指定输入的外观,但无论如何策略都将保持不变,我们将使用 $filter 遍历数组并仅匹配其 subarray 大小的文档等于基于给定输入的过滤子数组,如下所示:

// the current input structure.
inputArray = [
    {
        "key": "key1",
        "value": "abc"
    },
    {
        "key": "key2",
        "value": "value2"
    }
];
db.collection.aggregate([
  {
    $project: {
      array: {
        $filter: {
          input: "$array",
          as: "element",
          cond: {
            $and: [
              {
                $eq: [
                  {
                    $size: {
                      $filter: {
                        input: "$$element.nestedArray",
                        as: "nested",
                        cond: {
                          "$setIsSubset": [
                            [
                              "$$nested"
                            ],
                            inputArray
                          ]
                        }
                      }
                    },
                    
                  },
                  {
                    $size: "$$element.nestedArray"
                  }
                ]
              },
              {  // this is required for an exact match otherwise subsets are possible, if you wan't to allow it delete this equality completly.
                $eq: [
                  {
                    $size: "$$element.nestedArray"
                  },
                  {
                    $size: inputArray
                  }
                ]
              }
            ]
          }
        }
      }
    }
  }
])

同样,如果输入采用不同的结构,您将必须更改 $eq 条件

首先,展开 array 以便您可以轻松访问 nestedArray .

其次,在 nestedArray

上使用 $all 和 $elementMatch
db.collection.aggregate([
  {
    $unwind: "$array"
  },
  {
    $match: {
      "array.nestedArray": {
        $all: [
          {
            "$elemMatch": {
              key: "key1",
              value: "abc"
            }
          },
          {
            "$elemMatch": {
              key: "key2",
              value: "value2"
            }
          }
        ]
      }
    }
  },
  {
    $group: {
      _id: "$_id",
      array: {
        "$push": "$array"
      }
    }
  }
])

playground