有效地查询字段范围内缺失的整数?

时间:2016-06-12 22:44:20

标签: python mongodb performance database

我有一个备份服务数据库我正在编写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 个答案:

答案 0 :(得分:1)

在SQL word中,可以使用CTE,在mongo中我们可以使用$lookup聚合作为一种CTE(公用表表达式)

拥有此数据结构

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

缺少"mesId" : 5.0我们可以使用此聚合查询,该查询将投影所有下一个预期的ID,并加入它们。这里的限制是,如果我们按顺序丢失了多条消息,但可以通过预测下一个Id并再次进行$ lookup来扩展。

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" : []
}