【问题标题】:MongoDB query to return docs based on an array size after filtering array of JSON objects?MongoDB查询在过滤JSON对象数组后基于数组大小返回文档?
【发布时间】:2021-12-28 23:40:49
【问题描述】:

我有这样的 MongoDB 文档:

[
  {
    "id":  "car_1",
    "arrayProperty": [
      {
        "model": "sedan",
        "turbo": "nil"
      },
      {
        "model": "sedan",
        "turbo": "60cc"
      }
    ]
  },
  {
    "id":  "car_2",
    "arrayProperty": [
      {
        "model": "coupe",
        "turbo": "50cc"
      },
      {
        "model": "coupe",
        "turbo": "60cc"
      }
    ]
  }
]

我希望能够进行一个查找查询,将其翻译成基本英语为“忽略所有具有 'turbo' 的 'nil' 值的模型,返回所有具有长度为 X 的 arrayProperty 的文档。” 也就是说,汽车 1 的“arrayProperty”将被解释为大小为 1,而汽车 2 的数组大小为 2。目标是能够查询所有数组属性大小为 2 的汽车,并且只看到结果中返回的汽车 2。

不忽略 nil 值,查询很简单:

{ arrayProperty: { $size: 2} }

这将返回汽车 1 和 2。此外,如果我们的数组只是一个简单的数组,例如:

[1,2,3,'nil]

那么我们的查询就是:

{
  arrayProperty: {
    $size: X,
    $ne: "nil"
  }
}

但是,当我们引入 JSON 对象数组时,事情就变得棘手了。我尝试了很多事情都无济于事,包括:

  "arrayProperty": {
    $size: 2,
    $ne: {"turbo": "nil"}
  }

  "arrayProperty": {
    $size: 2,
    $ne: ["arrayProperty.turbo": "nil"]
  }

即使没有 $size 运算符,我似乎也无法按 nil 值进行过滤。有谁知道我将如何在最后两个查询中正确执行此操作?

【问题讨论】:

    标签: arrays mongodb aggregation


    【解决方案1】:

    $match中使用$and

    db.collection.aggregate([
      {
        $match: {
          "$and": [
            {
              arrayProperty: {
                $size: 2
              }
            },
            {
              "arrayProperty.turbo": {
                $ne: "nil"
              }
            }
          ]
        }
      }
    ])
    

    mongoplayground


    首先使用$set

    db.collection.aggregate([
      {
        "$set": {
          "arrayProperty": {
            "$filter": {
              "input": "$arrayProperty",
              "as": "a",
              "cond": {
                $ne: [
                  "$$a.turbo",
                  "nil"
                ]
              }
            }
          }
        }
      },
      {
        $match: {
          arrayProperty: {
            $size: 1
          }
        }
      }
    ])
    

    mongoplayground


    设置一个新的大小字段

    db.collection.aggregate([
      {
        "$set": {
          "size": {
            $size: {
              "$filter": {
                "input": "$arrayProperty",
                "as": "a",
                "cond": {
                  $ne: [
                    "$$a.turbo",
                    "nil"
                  ]
                }
              }
            }
          }
        }
      },
      {
        $match: {
          size: 1
        }
      }
    ])
    

    mongoplayground

    【讨论】:

    • 虽然这确实为这个特定查询返回了正确的汽车,但我正在寻找一个查询,如果我们将大小指定为 1,它也会返回汽车 1。这里的想法是,如果“turbo”是“nil”,那么我们根本不会将其计入大小。这可能吗?
    • 我更新我的答案
    • 酷,我想我也可以在 find {} 查询中使用 $expr 来使用它,因为这是聚合逻辑。请问您是否可以看到当我们查询大小为 1 时仍会包含“nil”值的方式?我看到它实际上被删除了。也许不可能,只是检查一下。
    • 我更新我的答案
    猜你喜欢
    • 2021-12-28
    • 2020-12-13
    • 2018-08-08
    • 2019-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-07
    相关资源
    最近更新 更多