1

的計數我現在有一個MongoDB的集合,看起來像這樣:排序方式過濾子文檔數組元素

{ 
    { 
     "_id": ObjectId, 
     "user_id": Number, 
     "updates": [ 
      { 
       "_id": ObjectId, 
       "mode": Number, 
       "score": Number 
      }, 
      { 
       "_id": ObjectId, 
       "mode": Number, 
       "score": Number 
      }, 
      { 
       "_id": ObjectId, 
       "mode": Number, 
       "score": Number 
      } 
     ] 
    } 
} 

我期待找到一種方法,找到每個模式更新的最大數量的用戶。例如,如果我指定模式0,我希望它按mode: 0以最大數量的更新順序加載用戶。

這在MongoDB中可能嗎?它不需要是一個快速算法,因爲它會被緩存很長一段時間,並且會異步運行。

回答

1

最快的方法是將存儲計數文檔中的每一個「模式」作爲另一個字段,那麼你可以只排序上:

var update = { 
    "$push": { "updates": updateDoc }, 
}; 

var countDoc = {}; 
countDoc["counts." + updateDoc.mode] = 1; 

update["$inc"] = countDoc; 

Model.update(
    { "_id": id }, 
    update, 
    function(err,numAffected) { 

    } 
); 

它將使用$inc遞增一個「罪狀」字段每個「模式」的價值爲每一個「模式」的關鍵推到「更新」陣列。所有的計算髮生在更新,所以它的速度快等特點是可以與該值排序應用查詢:

Model.find({ "updates.mode": 0 }).sort({ "counts.0": -1 }).exec(function(err,users) { 

}); 

如果你不想或者不能儲存這樣一個字段,則其他選項是在查詢時與.aggregate()計算:

Model.aggregate(
    [ 
     { "$match": { "updates.mode": 0 } }, 
     { "$project": { 
      "user_id": 1, 
      "updates": 1, 
      "count": { 
       "$size": { 
        "$setDifference": [ 
         { "$map": { 
          "input": "$updates", 
          "as": "el", 
          "in": { 
           "$cond": [ 
            { "$eq": [ "$$el.mode", 0 ] }, 
            "$$el", 
            false 
           ] 
          } 
         }}, 
         [false] 
        ] 
       } 
      } 
     }}, 
     { "$sort": { "count": -1 } } 
    ], 
    function(err,results) { 

    } 
); 

這是不壞,因爲數組的篩選和獲取$size相當effecient,但它不是一樣快,只使用一個存儲的值。

$map運算符允許內聯處理由$cond測試的數組元素,以查看它是否返回匹配項或false。然後$setDifference刪除任何錯誤的值。一種比使用$unwind更好的方法來過濾數組內容,這會使事情顯着減慢,除非您打算在文檔間聚合數組內容,否則不應使用它。

但更好的方法是存儲爲計數的值來代替,因爲這並不需要運行時計算,甚至可以使用索引

0

我覺得這是這個問題的一個副本:

Mongo find query for longest arrays inside object

接受的答案似乎在做你問什麼了。

db.collection.aggregate([ 
    { $unwind : "$l" }, 
    { $group : { _id : "$_id", len : { $sum : 1 } } }, 
    { $sort : { len : -1 } }, 
    { $limit : 25 } 
]) 

只是"$updates"取代"$l"

[編輯:]你可能不希望的結果限制爲25,所以你也應該擺脫{ $limit : 25 }

+0

因爲有更好的方法來計算陣列,如用這並不是非常有效的' $ size'。你也不會解決爲特定「模式」值要求「過濾計數」的問題。還有更有效的方法,例如在添加項目時在文檔本身內維護每個「模式」的計數。 –

+0

更重要的方面是按模式過濾。您是否能夠將此應用於此解決方案? – Redback93

+0

@ Redback93評論的要點是,這不是一個解決方案,實際上當時還有另一個答案,它展示瞭如何用兩種有效的方法獲得你想要的東西。 –