我在Windows Server 2008 R2上使用MongoDB,版本2.4.8,我有奇怪的索引行为,我无法解释。这是我在我的集合中的结构示例:
{
"_id" : NUUID("67070100-4627-4aa5-8ab9-45624e5b82ad"),
"PropertyType" : "Cooperative",
"Address" : {
"Street" : "aaaaaaaaa",
"HouseNo" : "165",
"PostalCode" : 2860,
"City" : "bbbbb",
"Floor" : "1",
"DoorNumber" : ""
},
"Sales" : {
"Price" : 425000,
"Payout" : 0,
"AreaPrice" : 9042,
"GrossPrice" : 2340,
"NetPrice" : 800,
},
"WithdrawnFromSale" : true,
"UnitData" : {
"UnitType" : "aaaaa",
"Area" : 400,
"LivingArea" : 50,
"UnitArea" : 50,
"Rooms" : 2,
"BuildYear" : 1948,
"GroundArea" : 203,
"NoiseLevel" : 5
}
}
另外,我为该集合创建了索引:
db["UnitModel"].ensureIndex({ "Sales": 1, "PropertyType": 1, "UnitData.Rooms": 1, "UnitData.NoiseLevel": 1 })
该索引存在的问题是,在使用此索引时,我的项目计数错误。
当我发出此请求时:
db.UnitModel.find({Sales: {$ne: null}, WithdrawnFromSale: false}).explain({verbose: true})
我得到以下结果:
{
"cursor" : "BtreeCursor Sales_1_PropertyType_1_UnitData.Rooms_1_UnitData.NoiseLevel_1 multi",
"isMultiKey" : false,
"n" : 19368,
"nscannedObjects" : 42875,
"nscanned" : 42876,
"nscannedObjectsAllPlans" : 43274,
"nscannedAllPlans" : 43276,
"scanAndOrder" : false,
"indexOnly" : false,
....
}
在这里我们可以看到已经使用了索引,但返回的项目数是“n”:19368。这是错误的。 应该是具有该标准的集合中的70986 项目。
为什么我确定它应该是更多的记录?嗯,这里是代码:
var totalCount = 0;
db.UnitModel.find({WithdrawnFromSale: false}).forEach(
function (e) {
if(e.hasOwnProperty('Sales') && e.Sales != null)
totalCount++;
}
)
totalCount;
totalCount = 70986
为了确保上面的查询不使用任何索引,让我们检查一下:
db.UnitModel.find({WithdrawnFromSale: false}).explain({verbose: true})
结果:
{
"cursor" : "BasicCursor",
"isMultiKey" : false,
"n" : 70986,
"nscannedObjects" : 3204212,
"nscanned" : 3204212,
"nscannedObjectsAllPlans" : 3204212,
"nscannedAllPlans" : 3204212,
"scanAndOrder" : false,
"indexOnly" : false,
....
}
因此,对于我正在使用的UnitModel集合,标准:销售:{$ ne:null},WithdrawnFromSale:false 它应该是mongo返回的70986条记录。但是你可以看到我弄错了。
有人可以解释一下为什么吗?可能是什么原因?
顺便说一句。当我删除该索引并使用以下索引时: db [“UnitModel”]。ensureIndex({“WithdrawnFromSale”:1}) 它按预期工作。但我不需要那个索引,这对我的情况并不乐观。
答案 0 :(得分:1)
与MongoDB 2.4一样,maximum size of an indexed value为1024字节。对于索引太大而无法索引的当前行为是在服务器端记录警告 - 但这不会引发异常。在这种情况下,当密钥太长时,密钥过长的文档将不包含在索引中,但将包含在其他索引中。这可能导致结果不一致,例如错误的计数和一个索引无法找到的“缺少文档”,但可能在另一个索引中或$natural
搜索中可用。
在MongoDB 2.5开发/不稳定分支(最终将在今年晚些时候发布MongoDB 2.6产品版本)中,这种行为发生了变化。与MongoDB 2.5.5一样,如果插入/更新包含密钥太大的索引更新,现在将引发异常。有关详细信息,请参阅MongoDB问题跟踪器中的SERVER-5290。
答案 1 :(得分:0)
找出问题的原因。当我查看monogodb的日志文件时,我看到了大量以下消息:
HBReadModel.system.indexes Btree :: insert:key太大而不能索引,跳过HBReadModel.UnitModel。$ Sales_1_WithdrawnFromSale_1_PropertyType_1_UnitData.Rooms_1_UnitData.NoiseLevel_1
我试图在 sales 字段上创建索引,该字段实际上是文档而非字段。为了避免这种情况,我只需重新创建索引并在 Sales 文档中指定字段。日志清除,查询按预期返回记录。