【问题标题】:Get distinct values from array based on conditions within the array根据数组中的条件从数组中获取不同的值
【发布时间】:2017-10-13 05:09:25
【问题描述】:

我有一个包含这样的文档的集合:

{
"_id" : ObjectId("59df91dae4b03289d79efb4e"),
  "name" : "TEST",
  "payload" : [ 
    {
      "_id" : "ABC",
      "status": "FALSE"
    },
    {
      "_id":"DEF",
     "status": "TRUE"
    },
    {
      "_id" : "XYZ",
     "status": "NULL"
    }
  ]
}

我正在尝试查找所有状态为 TRUE/FALSE 的 payload._id。 预期结果是

["ABC","DEF"]

到目前为止,我有这样的东西。

db.collection.distinct('payload._id',{"_id" : "TEST"})

不确定如何为数组中的元素添加条件。

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    .distinct() 的查询条件适用于“文档选择”,而不是文档“内”包含的数组条目。如果您需要“过滤”数组内容,则改为应用.aggregate(),并进行一些后期处理以仅获取数组响应中的“值”。

    db.collection.aggregate([
      { "$match": { "_id": "TEST" } },
      { "$unwind": "$payload" },
      { "$match": { "payload.status": { "$in": ["TRUE","FALSE"] } } },
      { "$group": { "_id": "$payload._id" } },
    ]).map( d => d._id );
    

    主要部分是$unwind 管道阶段,您这样做主要是因为您希望数组中的值稍后用作$group on 的键。这实质上为每个数组成员生成了一个新文档,但每个文档只包含该数组成员。它对包含数组的 MongoDB 结构进行“反规范化”。

    接下来是下面的$match 管道,它的工作方式与任何查询类似,并且只选择符合条件的文档。由于所有数组成员现在都是“文档”,因此不匹配的条目(作为文档)被排除在外。您可以交替使用$filter 来提取数组,但由于我们需要$unwind 用于下一阶段,我们也可以简单地使用$match

    此时,您只剩下与条件匹配的数组条目。 $group 用于获取“不同”值,因此通常您会在更广泛的选择范围内执行此操作,而不仅仅是单个文档或此处的值尚不明确的任何内容。所以这实际上只是保持.distinct() 的所有相同行为不变。

    最后,由于.aggregate() 的输出与.distinct() 的设计不同之处在于它在结果中返回“文档”,因此我们只需使用.map() 方法来处理游标结果并仅返回“值”从特定的文档属性作为“数组”。

    【讨论】:

    • 这行得通。感谢您的解释。修改 map() 方法如下,在 RoboMongo 上运行 map(function(u) { return u._id; })
    • @AtulPrasad 如果 RoboMongo 不理解箭头 => 函数的 ES6 语法,您可能拥有旧版本的 RoboMongo。我建议您更新它,因为还有与现代 MongoDB 版本的兼容性相关的其他更改。也欢迎来到 Stack Overflow。当您收到适合您问题的答案时,您mark it as accepted 表示正确答案。
    【解决方案2】:

    我正在尝试查找所有状态为 TRUE/FALSE 的 payload._id

    您要运行的查询是:

    db.collection.distinct('payload._id', { 
      'payload.status': { $in: ["TRUE", "FALSE"] } 
    })
    

    更详细的方法是:

    db.collection.distinct('payload._id', { 
      $or: [
        {'payload.status': "TRUE" },
        {'payload.status': "FALSE" }
      ]  
    })
    

    【讨论】:

    • .distinct() 中的查询条件不会“过滤”数组内容。 See the answer..
    猜你喜欢
    • 2021-11-28
    • 2022-09-27
    • 1970-01-01
    • 1970-01-01
    • 2018-07-10
    • 1970-01-01
    • 2020-11-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多