如果未使用正确的索引,MongoDB查询将失败

如果未使用正确的索引,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

例如,Mongo collection:

{ 
  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失败,因为它尝试先计算后面的条件。