MongoDB:根据其他对象设置集合中的值

时间:2018-03-03 08:31:58

标签: mongodb

问题

文档如下所示:

{
  data: [
    { identifier: 'a', value: 10 },
    { identifier: 'b', value: 53 },
    { identifier: 'c', value: 16 }
  ]
}

如果标识符为null的同一数组中的另一个对象符合条件,我想将所有值设置为x。现实生活中的例子:

如果标识为value的对象的属性a大于9,请设置标识为valueb的对象的属性cnull

方法

我正在尝试使用$project管道,但不知道如何找到其他对象。

// ... Rest
{
$unwind: '$data'
}, {
$project: {
  data: {
    identifier: 1,
    value: {
      $cond: {
        if: {}, // Implement
        then: null, // Only valid for current value
        else: '$row.value'
      }
    }
  }
}
// ... Rest

想要输出

生成的聚合应该是一个数组。

如果a的值符合条件:

[
  { data: { identifier: 'a', value: null } },
  { data: { identifier: 'b', value: null } },
  { data: { identifier: 'c', value: null } },
  // ... more documents
]

如果a的值不符合条件:

[
  { data: { identifier: 'a', value: 10 } },
  { data: { identifier: 'b', value: 53 } },
  { data: { identifier: 'c', value: 16 } },
  // ... more documents
]

2 个答案:

答案 0 :(得分:2)

您可以尝试以下聚合查询。

使用$cond表达式与$filter一起验证输入条件是否与数组中的任何元素匹配,并$size输出$gt的长度,而不是0比较;如果是,请使用$map将所有值映射为null;如果没有按原样保留数据值。

 db.colname.aggregate({"$addFields":{
  "data":{
    "$cond":[
      {"$gt":[
        {"$size":{
          "$filter":{
            "input":"$data",
            "as":"d",
            "cond":{
              "$and":[
                {"$eq":["a","$$d.identifier"]}, 
                {"$gt":["$$d.value", 9]}
              ]
            }
          }
        }}, 
        0
      ]}, 
      {"$map":{
        "input":"$data",
        "as":"d",
        "in":{ "identifier": "$$d.identifier", "value": null }
      }}, 
      "$data"
    ]
  }
}})

答案 1 :(得分:1)

尝试此聚合,而不使用$unwind

db.col.aggregate([
    {$addFields : {
        index : {$indexOfArray : ["$data.identifier", "a"]},
        isTrue : {$gte : [{$arrayElemAt : ["$data.value", {$indexOfArray : ["$data.identifier", "a"]}]}, 10]}
        }},
    {$addFields : {
        row : {
            identifier : {$arrayElemAt : ["$data.identifier", "$index"]},
            value : {$cond : ["$isTrue", {$arrayElemAt : ["$data.value", "$index"]}, null]}
        }
    }},
    {$project : {index :0, isTrue : 0, data : 0}}
]).pretty()

结果

> db.col.aggregate([ {$addFields : { index : {$indexOfArray : ["$data.identifier", "a"]}, isTrue : {$gte : [{$arrayElemAt : ["$data.value", {$indexOfArray : ["$data.identifier", "a"]}]}, 10]} }}, {$addFields : { row : { identifier : {$arrayElemAt : ["$data.identifier", "$index"]}, value : {$cond : ["$isTrue", {$arrayElemAt : ["$data.value", "$index"]}, null]} } }}, {$project : {index :0, isTrue : 0, data : 0}} ]).pretty()

{ "_id" : 1, "row" : { "identifier" : "a", "value" : 10 } }
> 

修改

使用$map将值设置为所有标识符的值

db.col.aggregate([
    {$addFields : { 
        isTrue : {$gte : [{$arrayElemAt : ["$data.value", {$indexOfArray : ["$data.identifier", "a"]}]}, 10]}
    }},
    {$addFields : {
        data : 
            {$map : {
                input : "$data",
                as : "d",
                in : {
                    identifier : "$$d.identifier",
                    value : {$cond : ["$isTrue", "$$d.value", null]}
                }
            }}
    }},
    {$project : {_id :0, isTrue : 0}}
]).pretty()

结果

{
    "data" : [
        {
            "identifier" : "a",
            "value" : 10
        },
        {
            "identifier" : "b",
            "value" : 53
        },
        {
            "identifier" : "c",
            "value" : 16
        }
    ]
}