如何在对象数组中搜索没有精确对象的条件?

时间:2017-08-08 11:28:03

标签: mongodb mongoose

我有一组人员,他们的架构看起来像是以下文件的集合。

    Document: {

    name:
    age:
    educations:[{
title:xyz,
passed_year:2005,
univercity:abc},
{
title:asd
passed_year:2007,
univercity:mno
}],
current_city:ghi
}

现在我想向所有未在2005年从abc大学完成xyz教育的人员展示。

我认为有两个可能的查询需要但不确定使用哪一个作为它们都给我输出

查询1:

  

db.persons.find({"教育" {的 $ NE :{$ elemMatch:{"标题":" XYZ&# 34;," passed_year":2005," univercity":" ABC"}}}})

查询2:

  

db.persons.find({"教育" {的 $不可以:{$ elemMatch:{"标题":" XYZ&# 34;," passed_year":2005," univercity":" ABC"}}}})

我对操作符$ ne和$ not非常困惑,我应该使用$ elemMatch,因为他们都给了我输出。

1 个答案:

答案 0 :(得分:1)

鉴于此$elemMatch{"title":"xyz","passed_year":2005,"univercity":"abc"}我认为您希望排除包含所有这些对的educations数组中包含子文档的任何文档:

  • “title”:“xyz”
  • “passed_year”:2005
  • “univercity”:“abc”

此查询将实现:

db.persons.find({
    "educations": {
        $not: {
            $elemMatch:{"title": "xyz", "passed_year": 2005, "univercity": "abc"}
         }
     }
})

在你的问题中你写道:

  

他们两个都在给我输出

我怀疑这是因为您的查询指定了education,而正确的属性名称是educations。通过指定education,您正在添加一个无法评估的谓词,因为它引用了不存在的文档属性,因此无论该谓词是使用$ne还是$not,它都不会被应用。< / p>

回答使用哪个运算符的问题:$not$ne:如果使用.explain(true)运行上述查询,您会注意到Mongo生成的解析查询是每个运营商都有很大不同。

  • 使用$ne

    "parsedQuery" : {
        "$not" : {
            "educations" : {
                "$eq" : {
                    "$elemMatch" : {
                        "title" : "xyz",
                        "passed_year" : 2005,
                        "univercity" : "abc"
                    }
                }
            }
        }
    }
    
  • 使用$not

    "parsedQuery" : {
        "$not" : {
            "educations" : {
                "$elemMatch" : {
                    "$and" : [ 
                        {
                            "passed_year" : {
                                "$eq" : 2005
                            }
                        }, 
                        {
                            "title" : {
                                "$eq" : "xyz"
                            }
                        }, 
                        {
                            "univercity" : {
                                "$eq" : "abc"
                            }
                        }
                    ]
                }
            }
        }
    }
    

所以,看起来使用$ne会导致Mongo做类似这样的伪代码......

not educations equalTo "$elemMatch" : {"title" : "xyz", "passed_year" : 2005, "univercity" : "abc"}

...即它将elemMatch子句视为相等操作的RHS,而使用$not会导致Mongo实际评估elemMatch子句。