MongoDB聚合但不包括某些项目

时间:2016-03-03 12:23:32

标签: mongodb aggregation-framework

我对MongoDB的聚合框架很新,所以我不知道如何做到这一点。

我的数据模型结构如下:

{
  name: String,
  store: {
    item1: Number,
    item2: Number,
    item3: Number,
    item4: Number,
  },
  createdAt: Date
}

我想要退回每件商品的平均价格' i'。我正在尝试使用此查询:

db.commerces.aggregate([
   {
      $group: {
        _id: "",
        item1Avg: { $avg: "$store.item1"},
        item2Avg: { $avg: "$store.item2"},
        item3Avg: { $avg: "$store.item3"},
        item4Avg: { $avg: "$store.item4"}
      }
   }
]);

问题在于,当某个商品没有设定价格时,它会以" -1"的形式存储在数据库中。

我不希望这些值污染平均结果。有没有办法限制agreggation只考虑价格> 0

$match之前的

$group运算符不是解决方案,因为我想返回所有平均价格。

谢谢!

编辑:这里有一个输入&的例子。期望的输出:

[{
  name: 'name',
  store: {
    item1: 10,
    item2: -1,
    item3: 12,
    item4: 3,
  }
},
{
  name: 'name2',
  store: {
    item1: 10,
    item2: -1,
    item3: -1,
    item4: 2,
  }
},...]

所需的输出:

{
  item1Avg: 10,
  item2Avg: 0,
  item3Avg: 12,
  item4Avg: 2.5
}

1 个答案:

答案 0 :(得分:1)

您需要$unwind store,然后$match值才能满足您的条件,然后$group通过测试。遗憾的是,无法$unwind一个对象,所以你需要$project首先排列一个对象:

db.commerces.aggregate([
    {$project: {store:[
        {item:{$literal:"item1"}, val:"$store.item1"}, 
        {item:{$literal:"item2"}, val:"$store.item2"}, 
        {item:{$literal:"item3"}, val:"$store.item3"}, 
        {item:{$literal:"item4"}, val:"$store.item4"}
    ]}},
    {$unwind:"$store"},
    {$match: {"store.val":{$gt:0}}},
    {$group: {_id:"$store.item", avg:{$avg:"$store.val"}}}
])

修改

正如@ blakes-seven指出的那样,它可能不适用于版本< 3.2。使用$map的替代方法可能有效:

db.commerces.aggregate([
    {$project: {
        store: {
            $map:{
                input:[
                    {item:{$literal:"item1"}, val:"$store.item1"},
                    {item:{$literal:"item2"}, val:"$store.item2"},
                    {item:{$literal:"item3"}, val:"$store.item3"},
                    {item:{$literal:"item4"}, val:"$store.item4"}
                ],
                as: "i",
                in: "$$i"
            }
        }
    }},
    {$unwind:"$store"},
    {$match: {"store.val":{$gt:0}}},
    {$group: {_id:"$store.item", avg:{$avg:"$store.val"}}}
])