2016-03-03 144 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

謝謝,添加了地圖示例。沒有任何古代版本方便測試壽。 –