2016-06-12 53 views
1

我正在寫一個備份服務的數據庫to backup Yahoo! Groups。它逐步檢索具有連續數字ID的消息。存儲在'message_id'字段中。因此,如果服務上的最後一條消息是消息號10000,那麼一旦備份完成,數據庫應該包含10000個文檔,每個文檔的排序的'message_id'等於range(1, 10000+1)在字段範圍內有效查詢丟失的整數?

我想寫一個查詢產生缺少的消息id。因此,如果我在數據庫中有9995個文檔,並且缺少消息10,15,49,99和1043,則應該返回[10, 15, 49, 99, 1043]

我已經做了以下,從數據庫中獲取只是id和我的應用程序代碼運行的交集:

def missing_message_ids(self): 
    """Return the set of the ids of all missing messages..""" 
    latest = self.get_latest_message() 
    ids = set(range(1, latest['_id']+1)) 
    present_ids = set(doc['_id'] for doc in self.db.messages.find({}, {'_id': 1})) 
    return ids - present_ids 

這是好的,我的目的,但它似乎像它可能太對於大量的消息來說很慢。這更多的是出於好奇而不是真正的性能要求:是否有更有效的方式來完成這個工作,或許完全是在數據庫引擎上?

回答

1
在SQL字一個可以使用的CTE,在蒙戈我們可以使用聚合與 $lookup作爲一種CTE具有這種數據結構

{ 
    "_id" : ObjectId("575deea531dcfb59af388e17"), 
    "mesId" : 4.0 
}, { 
    "_id" : ObjectId("575deea531dcfb59af388e18"), 
    "mesId" : 6.0 
} 

缺少"mesId" : 5.0

(公共表表達式)

我們可以使用這個聚合查詢,它將投影所有下一個預期的id,並加入它們。這裏的限制是,如果我們錯過了一個以上的消息,但是可以通過投射下一個Id並再次進行$查找來擴展。

var project = { 
    $project : { 
     _id : 0, 
     mesId : 1, 
     nextId : { 
      $sum : ["$mesId", 1] 
     } 
    } 
} 
var lookup = { 
    $lookup : { 
     from : "claudiu", 
     localField : "nextId", 
     foreignField : "mesId", 
     as : "missing" 
    } 
} 
var match = { 
    $match : { 
     missing : [] 
    } 
} 

db.claudiu.aggregate([project, lookup, match]) 

輸出:

{ 
    "mesId" : 4.0, 
    "nextId" : 5.0, 
    "missing" : [] 
}