2013-12-18 57 views
1

我有一個蒙戈集合,其中包含看起來像這樣的文件:

{ 
    "record" : "1", 
    "site_id" : "abc1", 
    "month" : "2013-12", 
    "recorded" : ISODate("2013-12-18T05:00:00.000Z"), 
    "status" : "OK", 
    "comment" : "blah blah blah..." 
} 

{ 
    "record" : "2", 
    "site_id" : "abc1", 
    "month" : "2013-12", 
    "recorded" : ISODate("2013-12-18T06:00:00.000Z"), 
    "status" : "OK", 
    "comment" : "blah blah blah..." 
} 

{ 
    "record" : "3", 
    "site_id" : "abc2", 
    "month" : "2013-12", 
    "recorded" : ISODate("2013-12-18T06:00:00.000Z"), 
    "status" : "OK", 
    "comment" : "blah blah blah..." 
} 

{ 
    "record" : "4", 
    "site_id" : "abc2", 
    "month" : "2013-12", 
    "recorded" : ISODate("2013-12-18T11:00:00.000Z"), 
    "status" : "ERROR", 
    "comment" : "something wrong" 
} 

{ 
    "record" : "5", 
    "site_id" : "abc2", 
    "month" : "2013-11", 
    "recorded" : ISODate("2013-11-17T08:00:00.000Z"), 
    "status" : "OK", 
    "comment" : "blah blah blah..." 
} 

我想用$組操作員作出貓鼬調用返回的所有值最新的記錄(由ISODate()確定)爲每個site_id的給定月份。所以,在2013-12的這個月,我想要回到記錄2(2013-12最新的abc1)和記錄4(最新的2013-12的abc2)。

我可以使用map/reduce函數來做到這一點,但我想知道它是否適用於Mongoose API和聚合框架(不調用map/reduce函數)。我覺得應該是這樣,但我一直無法使它工作!

+0

您可以編輯的問題,包括一些你做了什麼沒有工作的嘗試?通過聚合框架和流水線,最好是一步一步地工作。 – WiredPrairie

回答

0

當使用aggregate獲得各組的特定元素,你需要包括在第一把所需的元素各組的$group之前,你的管道中的$sort階段,這樣就可以使用$first運營商挑出來的您想從該組中的第一個文檔獲取的字段。

在shell:

db.test.aggregate(
    {$match: {month: '2013-12'}}, 
    {$sort: {recorded: -1}}, 
    {$group: { 
     _id: '$site_id', 
     record: {$first: '$record'}, 
     recorded: {$first: '$recorded'}, 
     status: {$first: '$status'}, 
     comment: {$first: '$comment'} 
    }}) 
1

假設您所有的文件都在相同的字段現在,您可以使用聚合框架找到一個月,網站的每個分組的「最後」的紀錄。

注意:雖然下面的查詢返回預期結果,但它不是過於高效或可縮放,因此您應該使用具有代表性的數據集進行測試。在第一步中,$group方法需要排序比您實際想要返回更多的數據。另一種方法是使用$sort$limit運行每個站點的聚合。對於聚合框架使用情況$sort$limit(因爲要保留的前n個結果的數量是已知的),MongoDB 2.4+具有an optimization,所以多個高效查詢的總體執行時間可能比單個低效率的查詢少。

樣品聚集:

db.sites.aggregate(

    // Need to sort first so "last" makes sense in the $group 
    { $sort: { 
     month : 1, 
     site_id: 1, 
     recorded: 1, 
    }}, 

    // Find the last monthly record for each site_id 
    { $group: { 
     _id: { "month" : "$month", site_id: "$site_id" }, 
     record: { $last: "$record" }, 
     site_id: { $last: "$site_id" }, 
     month: { $last: "$month" }, 
     recorded: { $last: "$recorded" }, 
     status: { $last: "$status" }, 
     comment: { $last: "$comment" } 
    }} 

) 

樣品結果:

{ 
    "result" : [ 
     { 
      "_id" : { 
       "month" : "2013-12", 
       "site_id" : "abc2" 
      }, 
      "record" : "4", 
      "site_id" : "abc2", 
      "month" : "2013-12", 
      "recorded" : ISODate("2013-12-18T11:00:00Z"), 
      "status" : "ERROR", 
      "comment" : "something wrong" 
     }, 
     { 
      "_id" : { 
       "month" : "2013-12", 
       "site_id" : "abc1" 
      }, 
      "record" : "2", 
      "site_id" : "abc1", 
      "month" : "2013-12", 
      "recorded" : ISODate("2013-12-18T06:00:00Z"), 
      "status" : "OK", 
      "comment" : "blah blah blah..." 
     } 
    ], 
    "ok" : 1 
}