如果未使用正确的索引,MongoDB查询将失败
例如,Mongo collection:如果未使用正确的索引,MongoDB查询将失败,mongodb,Mongodb,例如,Mongo collection: { entityId: 43212 jobExists: true, value: 75, ... parent: "Mogli" } { entityId: 12435 jobExists: false, reasonForNonExistence: "Too many arguments", value: 97, ... parent: "Baba" } 等等 请注意,仅包含jobExists:fals
{
entityId: 43212
jobExists: true,
value: 75,
...
parent: "Mogli"
}
{
entityId: 12435
jobExists: false,
reasonForNonExistence: "Too many arguments",
value: 97,
...
parent: "Baba"
}
等等
请注意,仅包含jobExists:false的记录还包含另一个名为ReasonForNonexience的字段,而其他记录没有该字段。
我在数据库里有大约1100万条记录
EntityId和jobExists字段上存在索引
当查询非常复杂的查询时,前两个条件是“entityId:xxx”和“jobExists:false”,其余查询将检查“ReasonForNonexience”字段上的条件
大多数情况下,查询成功,一切正常,但当mongo选择不使用entityId和jobExists上的索引时,他实际上也会尝试检查其他条件,导致字段ReasonForNoExistence出现未定义的异常
我的问题是,如果mongo没有使用索引,为什么他会失败,而很明显,他甚至应该检查其余的条件,因为前2个条件可以过滤掉文档
我能做些什么来避免这种情况并使其生效?
(我知道检查字段是否在查询中定义的选项……只是想看看是否有更好的方法)
谢谢
这是由我们的代码创建的查询,正在运行:
db.reports.find(
{"$and":
[
{"$and":
[
{"jobExists":false},
{"entityId":
{"$in":["878"]}
},
{"$or":
[
{"entries":{"$exists":false}},
{"entries":{"$size":0}},
{"entries":{"$elemMatch":{"invoicedAt":{"$exists":false}}}},
{"entries":{"$elemMatch":
{"$and":
[
{"invoicedAt":{"$lte":{"$date":1529366400000}}},
{"invoicedAt":{"$gte":{"$date":1483228800000}}}
]}
}}
]},
{"$or":
[
{"entries":{"$exists":false}},
{"entries":{"$size":0}},
{"entries":{"$elemMatch":{"country":{"$exists":false}}}},
{"entries":{"$elemMatch":{"country":
{"$in":["AT","BE","BG","HR","CY","CZ","DK","EE","FI","FR","DE","GR","HU","IE","IT","LV","LT","LU","MT","NL","PL","PT","RO","SK","SI","ES","SE","GB","NO","CH","RS"]}}}}
]}
]},
{"$or":
[
{"companyInfo.country":{"$exists":false}},
{"companyInfo.vatRegistrations":{"$exists":false}},
{"entries":{"$exists":false}},
{"entries":{"$size":0}},
{"entries":{"$elemMatch":{"country":{"$exists":false}}}},
{"entries":{"$elemMatch":{"invoicedAt":{"$exists":false}}}},
{"$and":
[
{"companyInfo.country":{"$exists":true}},
{"entries.0":{"$exists":true}},
{"$where":"function() {
function foreign(entry) {
return obj.companyInfo != null && entry.country != null && obj.companyInfo.country != entry.country;
}
function vatReg(entry) {
var vatRegs = obj.companyInfo.vatRegistrations == null ? [] : obj.companyInfo.vatRegistrations;
return vatRegs.some(function(reg) {
return entry.country == reg.country && (
reg.registrationDate.getTime() == ISODate(\"1970-01-01\").getTime() &&
reg.registrationEndDate.getTime() == ISODate(\"3000-01-01\").getTime()
|| (
entry.invoicedAt != null && entry.invoicedAt.getTime() >= reg.registrationDate.getTime() &&
entry.invoicedAt.getTime() <= reg.registrationEndDate.getTime() )
);
});
}
function check(entry) { return foreign(entry) && !vatReg(entry); }
return obj.entries.some(check);}"
}
]}
]}
]
}).count();
db.reports.find(
{“$and”:
[
{“$and”:
[
{“jobExists”:false},
{“entityId”:
{“$in”:[“878”]}
},
{“$or”:
[
{“条目”:{“$exists”:false},
{“条目”:{“$size”:0}},
{“entries”:{“$elemMatch”:{“invoicedAt”:{“$exists”:false}}},
{“条目”:{“$elemMatch”:
{“$and”:
[
{“发票日期”:{“$lte”:{“$date”:1529366400000}}},
{“invoicedAt”:{“$gte”:{“$date”:1483228800000}}
]}
}}
]},
{“$or”:
[
{“条目”:{“$exists”:false},
{“条目”:{“$size”:0}},
{“条目”:{“$elemMatch”:{“国家”:{“$exists”:false}}},
{“条目”:{“$elemMatch”:{“国家”:
{“$in”:[“AT”,“BE”,“BG”,“HR”,“CY”,“CZ”,“DK”,“EE”,“FI”,“FR”,“DE”,“GR”,“HU”,“IE”,“IT”,“LV”,“LT”,“LU”,“MT”,“NL”,“PL”,“PT”,“RO”,“SK”,“SI”,“ES”,“SE”,“GB”,“NO”,“CH”,“RS”]}}
]}
]},
{“$or”:
[
{“companyInfo.country”:{“$exists”:false},
{“companyInfo.vatRegistrations”:{“$exists”:false},
{“条目”:{“$exists”:false},
{“条目”:{“$size”:0}},
{“条目”:{“$elemMatch”:{“国家”:{“$exists”:false}}},
{“entries”:{“$elemMatch”:{“invoicedAt”:{“$exists”:false}}},
{“$and”:
[
{“companyInfo.country”:{“$exists”:true},
{“entries.0”:{“$exists”:true},
{“$where”:“函数(){
函数外部(输入){
返回obj.companyInfo!=null&&entry.country!=null&&obj.companyInfo.country!=entry.country;
}
函数vatReg(条目){
var vatRegs=obj.companyInfo.vatRegistrations==null?[]:obj.companyInfo.vatRegistrations;
返回vatRegs.some(函数(reg){
return entry.country==reg.country&&(
reg.registrationDate.getTime()==ISODate(\“1970-01-01\”).getTime()&&
reg.registrationEndDate.getTime()==ISODate(\“3000-01-01\”).getTime()
|| (
entry.invoicedAt!=null&&entry.invoicedAt.getTime()>=reg.registrationDate.getTime()&&
entry.invoicedAt.getTime()如果您能提供一个准确的示例查询和您看到的准确/错误消息,这将有助于更好地了解情况。还包括您正在使用的MongoDB的准确版本。数据集本身非常复杂,而且即使我愿意,我也无法透露它…查询本身更复杂!但我将附上它。我刚才在这里给出了一个概念,我看到,查询中的一个条件位于一个字段上,该字段不存在于所有文档中,但其他条件应该过滤掉这些文档。因此,如果mongo选择使用“正确”索引,则只扫描具有此属性的文档并返回结果,但如果使用另一个索引,则ry失败,因为它尝试先计算后面的条件。