我有一个包含大约10亿个文档的大量文档,这些文档(少于200个)中很少包含一些字段" rare_field
"。
我怎样才能尽快找到包含该字段的所有文件?
如果我只是这样做:
collection.find({ "rare_field" : { $exists : true }})
它超时了。 这可能需要数天才能完成,因此我不确定即使通过查询标记阻止超时也会有所帮助,但也许我错了。
我还可以编写一个脚本来浏览所有文档,但这会很慢,因为它需要通过网络传输所有10亿个文档到我的服务器,我想要一些不需要任何传递的解决方案电线上的数据,并且会很快。
注意:这是一个sharded
集合。
我会将当前的解决方案作为答案发布,但我不确定它是否100%正确,并且它没有我想要的那么快。
答案 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})
会强制查询获取所有结果,然后传递第一个结果。