快速搜索巨大的mongodb系列中非常罕见的领域

时间:2016-12-12 10:13:53

标签: mongodb mongodb-query query-performance

我有一个包含大约10亿个文档的大量文档,这些文档(少于200个)中很少包含一些字段" rare_field"。

我怎样才能尽快找到包含该字段的所有文件?

如果我只是这样做:

collection.find({ "rare_field" : { $exists : true }})

它超时了。 这可能需要数天才能完成,因此我不确定即使通过查询标记阻止超时也会有所帮助,但也许我错了。

我还可以编写一个脚本来浏览所有文档,但这会很慢,因为它需要通过网络传输所有10亿个文档到我的服务器,我想要一些不需要任何传递的解决方案电线上的数据,并且会很快。

注意:这是一个sharded集合。

我会将当前的解决方案作为答案发布,但我不确定它是否100%正确,并且它没有我想要的那么快。

2 个答案:

答案 0 :(得分:2)

如果没有rare-field的索引,在最坏的情况下,mongodb将需要遍历集合中的所有文档。在这种情况下,游标可能会超时,因此您需要向游标添加一个标志以防止它这样做。

在mongo shell中,这意味着一个类似的查询:

var cursor = db.collection.find({ "rare_field" : { $exists : true }}).noCursorTimeout();

如果您担心网络问题或其他问题会在光标填充batchSize匹配文档之前中断查询,那么您确实可以按照答案中的建议逐个获取文档,但是您需要按{ _id: 1 }排序,并使用noCursorTimeout()limit(1),即:

var doc = db.collection.find({ "rare_field" : { $exists : true }})
            .sort({ _id: 1 })
            .limit(1)
            .noCursorTimeout()
            .next();

然后按照建议,在向查询对象添加条件{ _id: { $gt: doc._id } }的同时重复查询,检索下一个文档。

答案 1 :(得分:0)

可能的解决方案是使用findOne而不是find:

var doc = collection.findOne({ "rare_field" : { $exists : true }});

然后循环以获取下一个:

var doc = collection.findOne({ _id : { $gt : doc._id}, "rare_field" : { $exists : true }});

但是,我并非100%确定这些调用必须向我提供_id订购的结果,而且我不确定单个findOne是否也不会超时。

我担心明确添加sort({_id : 1})会强制查询获取所有结果,然后传递第一个结果。