2012-11-23 85 views
24

假設我有一個名爲「上崗」集合(它實際上是一個更復雜的集合,職位過於簡單)結構如下:

> db.posts.find() 

{ "id" : ObjectId("50ad8d451d41c8fc58000003"), "title" : "Lorem ipsum", "author" : 
"John Doe", "content" : "This is the content", "tags" : [ "SOME", "RANDOM", "TAGS" ] } 

我希望這個集合要跨越數十萬甚至數百萬個,我需要通過標記查詢帖子並按標記對結果進行分組並顯示分頁結果。這就是聚合框架進來我打算使用的骨料()方法來查詢集合:

db.posts.aggregate(
    { "unwind" : "$tags" }, 
    { "group" : { 
     _id: { tag: "$tags" }, 
     count: { $sum: 1 } 
    } } 
); 

美中不足的是,創建分頁程序,我需要知道輸出數組的長度。我知道要做到這一點,你可以這樣做:

db.posts.aggregate(
    { "unwind" : "$tags" }, 
    { "group" : { 
     _id: { tag: "$tags" }, 
     count: { $sum: 1 } 
    } } 
    { "group" : { 
     _id: null, 
     total: { $sum: 1 } 
    } } 
); 

但是,這將丟棄前一個管道(第一組)的輸出。有沒有辦法將兩種操作合併在一起,同時保留每個管道的輸出?我知道整個聚合操作的輸出可以用某種語言轉換爲數組,並且可以計算內容,但是流水線輸出可能會超過16Mb的限制。另外,爲了獲得計數而執行相同的查詢看起來很浪費。

那麼獲得文件結果是否可以同時計數呢?任何幫助表示讚賞。

+2

你真的需要一個完全準確的總數,或將逼近呢?然後再次,它看起來像你正在計算所有帖子,所以這不僅僅是一個你可以做的count()操作嗎? – cirrus

+0

我實際上是在對一組帖子進行計數,所以count()不會。 – MervS

+0

完美的解決方案,以獲得總數,同時保留聚合管道結果 http://stackoverflow.com/a/39784851/3666966 –

回答

30
  1. 使用$project保存tagcounttmp
  2. 使用$pushaddToSettmp存儲到您的data列表中。

代碼:

db.test.aggregate(
    {$unwind: '$tags'}, 
    {$group:{_id: '$tags', count:{$sum:1}}}, 
    {$project:{tmp:{tag:'$_id', count:'$count'}}}, 
    {$group:{_id:null, total:{$sum:1}, data:{$addToSet:'$tmp'}}} 
) 

輸出:

{ 
    "result" : [ 
      { 
        "_id" : null, 
        "total" : 5, 
        "data" : [ 
          { 
            "tag" : "SOME", 
            "count" : 1 
          }, 
          { 
            "tag" : "RANDOM", 
            "count" : 2 
          }, 
          { 
            "tag" : "TAGS1", 
            "count" : 1 
          }, 
          { 
            "tag" : "TAGS", 
            "count" : 1 
          }, 
          { 
            "tag" : "SOME1", 
            "count" : 1 
          } 
         ] 
       } 
     ], 
     "ok" : 1 
} 
+0

我不知道你可以在'$ project'管道的新字段中包含多個字段。這正是我需要的。謝謝。 – MervS

+1

是否可以$ sort,$ skip或$限制使用此方法的數據?您不能在$ project之前限制數據,並且在沒有丟失「總數」的情況下我沒有辦法做到這一點。另外,{$ sort:{'data.count':1}}似乎不像通常在非聚合查詢中那樣工作。 –

3

我不知道你需要的聚合框架此以外計算的所有變量如:

db.posts.aggregate(
    { "unwind" : "$tags" }, 
    { "group" : { 
     _id: { tag: "$tags" }, 
     count: { $sum: 1 } 
    } } 
); 

對於每個標籤,你可以只使用正常的查詢語法通過分頁 - 像這樣:

db.posts.find({tags: "RANDOM"}).skip(10).limit(10) 
+0

這將工作,如果我正在搜索標籤「隨機」的所有職位,但我實際上是分組職位通過他們的標籤和由此產生的組是什麼是需要分頁。 – MervS

+0

啊,我不確定! – Ross