Mongo收集为例
{
entityId: 43212
jobExists: true,
value: 75,
...
parent: "Mogli"
}
{
entityId: 12435
jobExists: false,
reasonForNonExistence: "Too many arguments",
value: 97,
...
parent: "Baba"
}
等...
请注意,仅具有jobExists:false的记录还包含另一个名为reasonForNonExistence 的字段,而其他记录则没有。 数据库中大约有1100万条记录。
在EntityId和jobExists字段上存在索引。
查询非常复杂的查询时,前两个条件为“ entityId:xxx”和“ jobExists:false”,其余查询将在“ reasonForNonExistence”字段中检查条件。
大多数情况下,查询成功并且一切正常,但是,当mongo选择NOT时,不使用实体ID和jobExists上的索引,他实际上也尝试检查其他条件,从而导致字段原因ForNonExistence出现未定义的异常
我的问题是,如果mongo显然应该甚至检查其余条件,因为前2个可以将文档过滤掉,为什么mongo如果不使用索引就会失败?
如何避免这种情况并使之正常工作? (我知道检查查询中是否定义了字段的选项……只是想看看是否有更好的方法)
谢谢。
这是由我们的代码创建并运行的查询:
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();
我知道很难追踪。 请注意,前两个条件位于“ jobExist”字段和“ entityId”上 如果首先检查这两个条件(例如是否在jobExists和entityId上使用此索引),则所有其余文档都存在“ registrationEndDate”字段,因此“ where”子句下的查询可以工作。
但是如果选择了另一个索引,由于某种原因,它就像在运行2个条件之前尝试运行“ where”查询,以便它扫描不具有registrationEndDate字段并失败的文档,但出现以下异常:
“ exception”:“ reactivemongo.api.commands.LastError: DatabaseException ['TypeError:reg.registrationEndDate未定义 :\ nvatReg / <@:12:1 \ nvatReg @:9:1 \ ncheck @:22:31 \ n @:24:10 \ n'(代码= 139)] \ n“}