文本搜索上的MongoDB溢出排序阶段

Wal*_*ner 7 sorting text mongodb

使用MongoDB v2.6,如果从大型结果集中对游标进行排序以获得溢出,则这种情况并不少见.

cursor = db.collection.find( { "key" : "value" } )
cursor.sort( { "rank" : 1 } )  // This can blow up
Run Code Online (Sandbox Code Playgroud)

该错误看起来很像:

运行器错误:溢出排序阶段缓冲数据使用量为33598393字节超过内部限制33554432字节

在这种情况下,解决方案是为排序标准提供索引,而不仅仅是密钥.

db.collection.ensureIndex( { "rank" : 1 } )  // ascending
Run Code Online (Sandbox Code Playgroud)

这很美妙.


我在另一个地方遇到了这个问题,一个文本索引. 按照MongoDB手册中有关文本索引创建的说明,我完成了以下操作:

db.collection.ensureIndex(
   { "$**": "text" },
   { name: "TextIndex" }
)
Run Code Online (Sandbox Code Playgroud)

并且,这已在集合中所有ExtendedJSON对象的所有字段上创建了一个文本索引.

搜索工作完美.

cursor = db.collection.find( { "$text" : { "$search" : "NEEDLE" } } )
cursor.count()                      // w00t!  records that have NEEDLE in them
Run Code Online (Sandbox Code Playgroud)

但是,即使存在sort字段的索引,尝试执行之前工作的相同排序也会失败:

db.collection.ensureIndex( { "rank" : 1 } )  
cursor = db.collection.find( { "$text" : { "$search" : "NEEDLE" } } )
cursor.sort( { "rank" : 1 } )      // This blows up with the same error message
Run Code Online (Sandbox Code Playgroud)

运行器错误:溢出排序阶段缓冲数据使用量为33598393字节超过内部限制33554432字节


这是奇怪的部分.

迭代光标而不执行排序工作正常,这就是我如何计算上面.我甚至可以单步浏览光标并查看无序结果,因此文本搜索显然有效.

但是,省略文本搜索会导致排序正常工作; 这让我觉得它不是基于数量的,虽然我知道它实际上只是使用排序键的索引.

db.collection.ensureIndex( { "rank" : 1 } )  
cursor = db.collection.find( )     // Get absolutely everything
cursor.sort( { "rank" : 1 } )      // Well, sort now works again... hmm....
Run Code Online (Sandbox Code Playgroud)

正如我必须通过提供索引来"帮助"Mongo所以它可以排序而不将所有记录带入内存,如何为文本索引实现此目的?

不幸的是,我无法得到解释计划,因为它也会产生同样的错误.如果我对.find() sans .sort()的结果这样做,它会显示明显的 - 对数据的完整扫描,没有IndexBounds字段.


ADDENDUM:这不是一个字段,而是所有字段,我正在尝试文本索引 - 因此"$**".作为一个实验,我.ensureIndex(...)在所有字段上手动完成,希望这有助于排序.但请记住,我并不是要对文本字段进行排序 - 只是将其用作获取与搜索条件匹配的JSON对象集合的机制.一旦我拥有了该集合,并且我确实获得了该集合,我正在尝试按rank字段对其进行排序,该字段已经具有索引并且在其他方​​案中工作.

Ste*_*ack 0

也许这个链接会对您有所帮助。

总结一下:你不应该在程序中间调用ensureIndex,而应该让Mongoose为你调用它。只需将架构中的标志添加index: true到要用于排序的字段即可。就您而言,将其添加到排名和名称中应该没问题。至少这在我的项目中对我有用。

例子:

var schema = mongoose.Schema({
   ...
   normalText : String,
   rank : { type: Number, index: true},
   name : { type: String, index: true }
});
Run Code Online (Sandbox Code Playgroud)