2016-12-12 43 views
0

我有一个巨大的收藏与〜10亿文件,这些文件(少于200)包含一些字段“rare_field”很少。快速搜索非常罕见的领域在一个巨大的mongodb集合

我该如何尽快找到包含该字段的所有文档?

如果我简单地做:

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

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

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

备注:这是一个sharded集合。

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

+0

将这个'rare-field'放入分片查询中!正因为如此,mongo也会对这个领域进行索引!所以它会很快! –

+0

谢谢。这是一次性的事情,所以我并不需要索引。 这可能是一个很好的解决方案,当数据库是空的,但索引这个领域现在需要很多时间,就像手工检查所有文档(我认为) – marmor

+0

你是正确的时间消耗!所以这完全取决于你的应用程序!另一种方法是将结果保存在缓存中!将结果存储在新的集合中,或存储在redis或smtn中! –

回答

2

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

在蒙戈外壳,这将意味着像查询:

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 } }条件添加到查询对象来检索下一个文档。

0

一个可能的解决方案是使用findOne,而不是发现的:

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})会强制查询获取所有结果,然后传递第一个结果。

+0

我不认为这会是一个好主意!就像你做最糟糕的事情一样!你是mongo会做'find({“rare_field”:{$ exists:true}});'会做!但是你有很多开销将它分成几块。 –

+0

你的恐惧也有点解释你为什么不应该这样做!:) –