【问题标题】:how to test each element of array in mongodb subdocument如何测试mongodb子文档中数组的每个元素
【发布时间】:2019-09-18 13:06:37
【问题描述】:

我有包含以下数据的 mongodb 文档:

    amenities[
{
    amenity_id:52,
    Amenity:"AC"
},
{
    amenity_id:23,
    Amenity:"Free Parking"
}
]

我想将数组的每个amenity_id 元素与特定值匹配,并使用条件$cond 返回真或假。我用过

"$project":{'Free Parking':{'$cond':{'if':{'$in':['amenities.amenityId',[23]]},'then':'True','else':'False'}}

如果文档包含amenity_id= 52,则查询必须返回 False。 无论menityId如何,它都返回错误。可以列出设施 ID,因此使用$in。我如何测试每个元素?

【问题讨论】:

  • 我能够通过在一个阶段收集所有 id 并将值与下一阶段的列表进行比较来解决这个问题
  • 您是否在查询符合条件的文档?还是做别的事?您可以使用 $all 在数组中找到满足多个条件的文档。
  • 为什么你在一个地方有_id,然后在你的代码中测试amenityId
  • 我的错。我现在更新了问题。
  • 你在一个地方还有amenityId,在另一个地方还有amenity_id。我想知道这是否是您问题的核心,但如果它有效,我猜它在您的代码中是正确的,只是在示例代码或文档中不正确。

标签: mongodb mongodb-query pymongo


【解决方案1】:

考虑到您的输入集合是

[
  {
    amenities: [
      {
        _id: 52,
        Amenity: "AC"
      },
      {
        _id: 23,
        Amenity: "Free Parking"
      }
    ]
  }
]

使用聚合管道 $map

db.collection.aggregate([
  {
    $project: {
      amenites: {
        $map: {
          input: "$amenities",
          as: "item",
          in: {
            Amenity: "$$item.Amenity",
            _id: "$$item._id",
            isValid: {
              $cond: {
                if: {
                  $eq: [
                    "$$item._id",
                    23
                  ]
                },
                then: true,
                else: false
              },

            }
          }
        }
      }
    }
  }
])

你会得到如下结果:

[
  {
    "amenites": [
      {
        "Amenity": "AC",
        "_id": 52,
        "isValid": false
      },
      {
        "Amenity": "Free Parking",
        "_id": 23,
        "isValid": true
      }
    ]
  }
]

【讨论】:

    【解决方案2】:

    在 mongodb 中使用 $unwind 操作,它会将数组字段展开到多个文档中

    请参考这个网址 - https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/

    例如:

    {
      _id :1,
      field: [1,2,3]
    }
    

    这将使用 $unwind 转换为以下内容,

    [
        {_id, field:1},
        {_id, field:2},
        {_id, field:3}
    ]
    

    $unwind 之后,您可以运行匹配查询,使用$in 查询,

    例如:

    {
     $match: {
       field: {$in: [1,2]} 
     }
    }
    

    【讨论】:

    • 展开是不必要的,它现在会破坏原始文件。
    • @AsyaKamsky 聚合查询不会修改任何原始文档,也不会发生,您能告诉我有关您遇到的问题的更多详细信息吗?
    • 关键是当你使用 $unwind 时,聚合管道会改变文档的数量和它们的形状(在管道中)——所以无论你想对它们做什么之后 $unwind 使用的文档与存储在集合中的文档不同。我并不是说它对磁盘上的文档做任何事情,但是当问题是“我如何测试 X 文档”时,更改文档将不再返回他们想要测试的原始文档。
    猜你喜欢
    • 1970-01-01
    • 2012-09-28
    • 1970-01-01
    • 2014-04-01
    • 2016-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多