2016-03-03 122 views
-1

我对MongoDB的聚合框架非常陌生,所以我不知道如何做到这一点。MongoDB聚合但不包括某些项目

我有一个结构类似这样的数据模型:

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

我要回报每一位item'i平均价格”。我试着用这个查询:

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

问题是,当一个项目没有设置价格时,它以“-1”的形式存储在数据库中。

我不希望这些值污染平均结果。是否有任何方法来限制集合,只考虑当价格> 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 
} 
+0

你能告诉与预期结果的有效证件? – styvane

+0

使用$ redact操作。 – ZeMoon

+0

文档模式是不够的。请发布示例有效的JSON文档 – Saleem

回答

1

您需要$unwindstore,然后$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"}}} 
]) 

编辑:

正如@布雷克个尖,它可能无法在< 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"}}} 
]) 
+0

您可能会注意到,这只适用于MongoDB 3.2(可能是3.x,不知道更改何时),因为您不能像在早期版本中那样声明“store”数组。相反,使用'$ map'将可移植到2.6以上,并且还有另一种用于以前版本的数组映射技术。大部分注意到'$ map'和'$ filter'实际上会做得更好,因为它已经与MongoDB 3.2绑定了。 –

+0

谢谢,添加了地图示例。没有任何古代版本方便测试寿。 –