2012-12-24 120 views
4

取得與排序文件我有子文檔的文檔看起來是這樣的:MongoDB中通過計數

{ 
    "name" : "some name1" 
    "like" : [  
      { "date" : ISODate("2012-11-30T19:00:00Z") }, 
      { "date" : ISODate("2012-12-02T19:00:00Z") },  
      { "date" : ISODate("2012-12-01T19:00:00Z") }, 
      { "date" : ISODate("2012-12-03T19:00:00Z") } 
    ]  
} 

是否有可能(在過去7天的平均值)獲取文件「最喜歡」和按計數排序?

+2

是的,你可以使用[聚合框架](http://docs.mongodb.org/manual/applications/aggregation/)來做這樣的查詢。 – JohnnyHK

回答

8

有幾種不同的方法可以解決這個問題。我將關注的解決方案使用mongodb的聚合框架。首先,這裏是一個聚合管道,它可以解決你的問題,接下來是對命令中發生的事情的解釋/分解。

db.testagg.aggregate( 
    { $unwind : '$likes' }, 
    { $group : { _id : '$_id', numlikes : { $sum : 1 }}}, 
    { $sort : { 'numlikes' : 1}}) 

此管道具有3個主要的命令:

1)放卷:使得存在1 '喜歡' 每個文檔元素

2)組這個分割了 '喜歡' 字段:這使用_id字段重新組合文檔,爲找到的每個文檔遞增numLikes字段。這將導致numLikes被填充一個數字,該數字等於之前「喜歡」的元素的數量

3)Sort:最後,我們按照numLikes的升序對返回值進行排序。在測試我跑這個命令的輸出是:

for (var i=0; i < 100; i++) { 
    db.testagg.insert({_id : i}) 
    for (var j=0; j < i; j++) { 
     db.testagg.update({_id : i}, {'$push' : {'likes' : j}}) 
    } 
} 

請注意,這並不能完全回答你的問題,因爲它避免了採摘的問題:

{"result" : [ 
    { 
     "_id" : 1, 
     "numlikes" : 1 
    }, 
    { 
     "_id" : 2, 
     "numlikes" : 2 
    }, 
    { 
     "_id" : 3, 
     "numlikes" : 3 
    }, 
    { 
     "_id" : 4, 
     "numlikes" : 4 
    }.... 

這是數據通過插入日期範圍,但它應該讓你開始並朝着正確的方向前進。

當然,還有其他方法可以解決這個問題。一種解決方案可能是僅執行客戶端的所有排序和操作。這只是獲取您想要的信息的一種方法。

編輯:如果你發現這有點乏味,有一個票據添加一個$尺寸的運算符到聚合框架,我邀請你觀看,並可能upvote它試圖加快這個新的運算符,如果你是感興趣。

7

一個更好的解決辦法是保持一個計數字段,將記錄有多少喜歡這個文件。雖然你可以使用聚合來做到這一點,但性能可能不會很好。在計數字段上有一個索引將使讀操作更快,並且可以在插入新喜歡時使用原子操作來增加計數器。

1

您可以使用MongoDB的從V3.4開始下面這個簡化上述聚集查詢:

> db.test.aggregate([ 
    { $unwind: "$like" }, 
    { $sortByCount: "$_id" } 
]).pretty() 

{ "_id" : ObjectId("5864edbfa4d3847e80147698"), "count" : 4 } 

另外,作爲@ACE說你現在可以投影,而不是內使用$大小:

db.test.aggregate([ 
    { $project: { count: { $size : "$like" } } } 
]); 

{ "_id" : ObjectId("5864edbfa4d3847e80147698"), "count" : 4 }