当尝试对mongodb集合进行查找和排序时,我得到以下错误。该集合根本不大 - 我只有28个文档,当我超过23个记录的限制时,我开始收到此错误。
该文档的特殊之处在于它内部包含一个大型ArrayCollection但我根本没有获取该特定字段,我只是想获取一个DateTime字段。
db.ANEpisodeBreakdown.find({creationDate: {$exists:true}}, {creationDate: true} ).limit(23).sort( { creationDate: 1}
{ "$err" : "too much data for sort() with no index. add an index or specify a smaller limit", "code" : 10128 }
答案 0 :(得分:1)
所以这里的问题是32MB限制,你没有可以用作“仅索引”或“覆盖”查询的索引来获得结果。如果没有这个,你的“大字段”仍会被加载到数据中进行排序。
易于复制;
var string = "";
for ( var n=0; n < 10000000; n++ ) {
string += 0;
}
for ( var x=0; x < 4; x++ ) {
db.large.insert({ "large": string, "date": new Date() });
sleep(1000);
}
所以这个查询会爆炸,除非你限制为3:
db.large.find({},{ "date": 1 }).sort({ "date": -1 })
要克服这个问题:
在日期(以及其他使用过的字段)上创建索引,以便在覆盖的索引查询中不加载整个文档:
db.large.ensureIndex({ "date": 1 })
db.large.find({},{ "_id": 0, "date": 1 }).sort({ "date": -1 })
{ "date" : ISODate("2014-07-07T10:08:33.067Z") }
{ "date" : ISODate("2014-07-07T10:08:31.747Z") }
{ "date" : ISODate("2014-07-07T10:08:30.391Z") }
{ "date" : ISODate("2014-07-07T10:08:29.038Z") }
请不要索引和使用聚合,因为$project
不会受到与文档在传递给$sort
之前实际更改相同的限制。
db.large.aggregate([
{ "$project": { "_id": 0, "date": 1 }},
{ "$sort": {"date": -1 }}
])
{ "date" : ISODate("2014-07-07T10:08:33.067Z") }
{ "date" : ISODate("2014-07-07T10:08:31.747Z") }
{ "date" : ISODate("2014-07-07T10:08:30.391Z") }
{ "date" : ISODate("2014-07-07T10:08:29.038Z") }
无论哪种方式都可以获得限制下的结果,而无需以任何方式修改游标限制。
答案 1 :(得分:0)
如果没有索引,您可以用于排序的大小只会扩展到shellBatchSize
,默认情况下为20。
DBQuery.shellBatchSize = 23;
这应该可以解决问题。
答案 2 :(得分:0)
问题是在这个特定场景中的投影仍然会加载整个文档,它只是将它发送到您的应用程序而没有大型数组字段。
因此,MongoDB仍在为其32mb限制排序太多数据。