在mongo查询数组中编写条件乘法逻辑

时间:2016-10-16 06:22:26

标签: mongodb mongoose

我有一个json数据如下:

   [{
     finale: [ { sign: '~', prob: 0.5 }, 
               { sign: '~', prob: 0.4 } ] 
    },
    {
     finale: [ { sign: '~', prob: 0.7 }, 
               { sign: '>', prob: 0.25 } ] 
    }]

现在我想要的结果是这样的:

 [{
   result : {
             sign: '~', prob: 0.2 
            }
  },
  {
   result : {
             sign: '>', prob: 0.25 
            }     
  }]

这是我推导的逻辑:

如果“结局”中的数组元素为'拥有所有"〜"在'签署'元素,然后我希望结果具有所有' prob'的乘法。数组中的字段恰好是:

 0.5 * 0.4 = 0.2

但是,如果至少有一个标志是'>'或者'<&#;我只需要从“' sign'中复制完全相同的东西。和' prob'在结果中忽略所有其他值,如上面第二个结果所示

  

[注意:只能有一个'<'或者'>'在数组中。 “finale”中的数组元素'最多可以有3个元素,但它至少应该包含1个元素。元素的顺序也可以是随机的。]

1 个答案:

答案 0 :(得分:1)

我正在使用 MongoDB聚合框架。

此查询适用于此限制: 在每个文件中不能存在多于1"<"或1">"。基本上每个对象可以有多个"〜"但是0或1">"或"<"。

重点是逐个分组,然后拒绝每个对象有"〜"除了它只有"〜"的情况。

db.Test1.aggregate([
{
  $unwind:"$finale"
},
{
  $group:{
    _id: {_id: "$_id", sign:"$finale.sign"},
    finaleitems:{$push:"$finale"}
  }
},
{
  $match: {
    $or: [
       {$and:[  {finaleitems: {$size: 1}}, {$or:[   {"_id.sign":">"}, {"_id.sign":"<"}  ]}  ]},
       {$or:[  {finaleitems: {$size: 2}}, {finaleitems: {$size: 3}}     ]}
    ]
  }
},
{
  $project: {
    _id: 1,
    finaleitems: 1,
    result: {
      $cond: [{$eq:["$_id.sign","~"]}, 

      {
        $reduce: {
        input: "$finaleitems",
        initialValue: 1,
        in: { $multiply : ["$$value", "$$this.prob"] }
       }   
      }, 

      {$arrayElemAt:["$finaleitems",0]}]
    }
  }
}
]);

<强> INPUT

{ 
    "_id" : ObjectId("58033a8bd63cf401292fe09a"), 
    "finale" : [
        {
            "sign" : "~", 
            "prob" : 0.5
        }, 
        {
            "sign" : "~", 
            "prob" : 0.4
        }
    ]
}
{ 
    "_id" : ObjectId("58033a98d63cf401292fe09d"), 
    "finale" : [
        {
            "sign" : "~", 
            "prob" : 0.7
        }, 
        {
            "sign" : ">", 
            "prob" : 0.25
        }
    ]
}
{ 
    "_id" : ObjectId("58035251d63cf401292fe0a0"), 
    "finale" : [
        {
            "sign" : "<", 
            "prob" : 0.7
        }, 
        {
            "sign" : "~", 
            "prob" : 0.25
        }
    ]
}
{ 
    "_id" : ObjectId("5803622dd63cf401292fe0a3"), 
    "finale" : [
        {
            "sign" : "~", 
            "prob" : 0.7
        }, 
        {
            "sign" : ">", 
            "prob" : 0.25
        }
    ]
}

<强>输出

{ 
    "_id" : {
        "_id" : ObjectId("5803622dd63cf401292fe0a3"), 
        "sign" : ">"
    }, 
    "finaleitems" : [
        {
            "sign" : ">", 
            "prob" : 0.25
        }
    ], 
    "result" : {
        "sign" : ">", 
        "prob" : 0.25
    }
}
{ 
    "_id" : {
        "_id" : ObjectId("58035251d63cf401292fe0a0"), 
        "sign" : "<"
    }, 
    "finaleitems" : [
        {
            "sign" : "<", 
            "prob" : 0.7
        }
    ], 
    "result" : {
        "sign" : "<", 
        "prob" : 0.7
    }
}
{ 
    "_id" : {
        "_id" : ObjectId("58033a98d63cf401292fe09d"), 
        "sign" : ">"
    }, 
    "finaleitems" : [
        {
            "sign" : ">", 
            "prob" : 0.25
        }
    ], 
    "result" : {
        "sign" : ">", 
        "prob" : 0.25
    }
}
{ 
    "_id" : {
        "_id" : ObjectId("58033a8bd63cf401292fe09a"), 
        "sign" : "~"
    }, 
    "finaleitems" : [
        {
            "sign" : "~", 
            "prob" : 0.5
        }, 
        {
            "sign" : "~", 
            "prob" : 0.4
        }
    ], 
    "result" : 0.2
}

正如您所看到的,返回的属性更多,您不需要它们,但我认为这对于调试管道正在生成的内容是有益的。

我使用具有$reduce功能的Mongo DB 3.4RC: https://docs.mongodb.com/master/reference/operator/aggregation/reduce/

希望这可以解决您的问题。