MongoDB:查找数组中某个字段始终为真的所有文档

MongoDB: Finding all documents for which a certain field in an array is always true

这是我在官方MongoDB documentation上找到的bios合集:

    {
        "_id" : 1,
        "name" : {
            "first" : "John",
            "last" : "Backus"
        },
        "awards" : [
            {
                "award" : "W.W. McDowell Award",
                "year" : 1967,
                "by" : "IEEE Computer Society",
                "monetaryRewards": false
            }
        ]
    },
    {
        "_id" : 2,
        "name" : {
            "first" : "John",
            "last" : "McCarthy"
        },
        "awards" : [
            {
                "award" : "Turing Award",
                "year" : 1971,
                "by" : "ACM",
                "monetaryRewards": true
            },
            {
                "award" : "Kyoto Prize",
                "year" : 1988,
                "by" : "Inamori Foundation",
                "monetaryRewards": true
            }
        ]
    },
    {
        "_id" : 3,
        "name" : {
            "first" : "Grace",
            "last" : "Hopper"
        },
        "awards" : [
            {
                "award" : "Computer Sciences Man of the Year",
                "year" : 1969,
                "by" : "Data Processing Management Association",
                "monetaryRewards": true
            },
            {
                "award" : "Distinguished Fellow",
                "year" : 1973,
                "by" : " British Computer Society",
                "monetaryRewards": true
            },
            {
                "award" : "W. W. McDowell Award",
                "year" : 1976,
                "by" : "IEEE Computer Society",
                "monetaryRewards": false
            }
        ]
    }

我正在尝试编写一个查询,使我能够检索所有 monetaryRewards 都为真的文档。因此,考虑到以前的文件:

_id = 1 -> there is only one monetaryRewards and it is false. The query should not select it;
_id = 2 -> There are three awards and the monetaryRewards fields are always true. The query should select it;
_id = 3 -> There are three awards where monetaryRewards is twice true and once false. The query should not select it;

我写了以下查询:

    db.bios.find( { awards: {$not: {$elemMatch:{"monetaryRewards":false}}}} )

查询工作正常。后来我意识到我的 bios 集合也可能不包含 monetaryRewards 字段,例如可能有另一个文档:

    {
           "_id" : 4,
           "name" : {
               "first" : "Kristen",
               "last" : "Nygaard"
           },
           "awards" : [
               {
                   "award" : "Rosing Prize",
                   "year" : 1999,
                   "by" : "Norwegian Data Association",
                   "monetaryRewards":true
               },
               {
                   "award" : "Turing Award",
                   "year" : 2001,
                   "by" : "ACM"
               }
       }

在这种情况下,我的查询失败了,因为它将缺少 monetaryRewards 视为 true,而在我的情况下它应该是 false。

如何解决我的查询?

在这里你可以找到 mongoplayground ,你可以看到错误选择了 _id=4 的文档。

您可以 $map awards.monetaryRewards 到辅助布尔数组。使用 $ifNull 来满足缺少字段的情况。然后使用$allElementsTrue进行过滤。

db.collection.aggregate([
  {
    "$addFields": {
      "filterArr": {
        "$map": {
          "input": "$awards",
          "as": "a",
          "in": {
            $ifNull: [
              "$$a.monetaryRewards",
              false
            ]
          }
        }
      }
    }
  },
  {
    "$match": {
      $expr: {
        "$allElementsTrue": "$filterArr"
      }
    }
  },
  {
    $project: {
      filterArr: false
    }
  }
])

这里是Mongo playground供您参考。