簡體   English   中英

獲取具有不同標准的最新文檔

[英]Get last documents with a distinct criteria

情況

我無法想出一個很好的方法來進行某個MongoDb查詢。 首先,這是我想要做什么樣的查詢。 假設一個簡單的數據庫通過電子卡刷卡記錄進入和退出事件(可能還有其他操作,無關緊要)。 所以有一個名為swipelog的集合,其中包含如下所示的簡單文檔:

{
    _id: ObjectId("524ab4790a4c0e402200052c")
    name: "John Doe", 
    action: "entry",
    timestamp: ISODate("2013-10-01T1:32:12.112Z") 
}

現在我想列出名稱及其最后輸入時間(以及我可能想要的任何其他字段,但下面的示例僅使用這兩個字段)。

當前解決方案

以下是我現在所擁有的,作為MongoDb JavaScript控制台的“一線”:

db.swipelog.distinct('name')
           .forEach( function(name) {

    db.swipelog.find( { name: name, action:"entry" } )
               .sort( { $natural:-1 } )
               .limit(1)
               .forEach( function(entry) {

        printjson( [ entry.name, entry.timestamp ] )
    }) 
})

其中印有以下內容:

[ "John Doe", ISODate("2013-10-01T1:32:12.112Z")]
[ "Jane Deo", ISODate("2013-10-01T1:36:12.112Z")]
...

我認為上面有明顯的縮放問題。 如果有一百個名稱,那么將對數據庫進行1 + 100次查詢。 那么獲得“每個不同name最后timestamp ”的好/正確方法是什么? 如果更容易,更改數據庫結構或添加一些集合是可以的。

您可以使用聚合框架來實現此目的:

 db.collection.aggregate(
          [
             {$match:
                  {action:'entry'}
             },
             {$group:
                  {_id:'$name',
                   first:
                         {$max:'$timestamp'}
                  }
             }
          ])

如果您可能在結果中包含其他字段,則可以使用$ first運算符

 db.collection.aggregate(
          [
             {$match:
                  {action:'entry'}
             },
             {$sort:
                  {name:1, timestamp:-1}
             },
             {$group:
                  {_id:'$name',
                   timestamp: {$first:'$timestamp'},
                   otherField: {$first:'$otherField'},
                  }
             }
          ])

這個答案應該是對attish上面的回答的評論,但我沒有足夠的代表來評論

請記住,聚合框架不能返回超過16MB的數據 如果您擁有大量用戶,則可能會在生產系統上遇到此限制。

MongoDB 2.6為聚合框架添加了新功能來處理這個問題:

  • db.collection.aggregateCursor() (臨時名稱)與db.collection.aggregate()完全相同,只是它返回游標而不是文檔。 這避免了16MB的限制
  • $out是一個新的管道階段,它將管道的輸出定向到一個集合。 這允許您運行聚合作業
  • $sort已得到改進,以消除其RAM限制並提高速度

如果查詢性能比數據時代更重要,您可以安排一個常規aggregate命令,將其結果存儲在集合中,如db.last_swipe ,然后讓您的應用程序只查詢相關用戶的db.last_swipe

結論:我同意attish有正確的方法。 但是,您可能在當前的MongoDB版本上縮放它時遇到麻煩,應該查看Mongo 2.6。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM