MongoDB - 在$ elemMatch中使用$ where

时间:2016-03-22 10:36:05

标签: mongodb mongodb-query

我们说我有一个帐户集合,每个帐户都有一组用户:

{
  _id: 1,
  users: [
    {
      firstName: a,
      lastName: b
    },
    {
      firstName: c,
      lastName: c
    }
  ]
}

我想查询至少有一个用户具有相同firstNamelastName

的所有帐户

我试着这样做:

db.accounts.find({users: {
    $elemMatch: {
        $where: "this.firstName == this.lastName"
    }
}})

但当然因为这个错误而无法正常工作:

  

无法规范查询:BadValue $ elemMatch不能包含$ where表达式

我想使用find而非aggregate。 还有其他方法吗?

3 个答案:

答案 0 :(得分:4)

请尝试将$whereArray.some一起使用,如下所示。

> db.collection.find({
             $where: function() {
                  return this.users.some(function(obj){ 
                           return obj.firstName == obj.lastName;
                 })
            }})

答案 1 :(得分:2)

开箱即用,但由于$where依赖于JavaScript评估,因此使用$redact的聚合实际上应该运行得更快,因为它使用本机运算符:

db.collection.aggregate([
    { "$redact": {
        "$cond": {
            "if": {
                "$anyElementTrue": {
                    "$map": {
                        "input": "$users",
                        "as": "user",
                        "in": { "$eq": [ "$$user.firstName", "$$user.lastName" ] }
                    }
                }
            },
            "then": "$$KEEP",
            "else": "$$PRUNE"
        }
    }}
])

因此$anyElementTrue$map结合使用基本上与JavaScript .some()相同,因为如果任何元素实际上与"firstName"相同"lastName"然后,这是一个true匹配,文档是"保持"。否则它将被修剪"并丢弃。

因此,使用本机运营商的速度,我会考虑$where以上的评估。我知道你说你不想,但你可能不认为这个说法很简单,或者比其他选择快得多。

答案 2 :(得分:0)

documentation非常清楚:

  

您不能将$ where表达式指定为$ elemMatch的查询条件。

你可以做的是在$where内迭代数组:

db.collection.find(function(){
    for(var i in this.users) {
        if(this.users[i].firstName == this.users[i].lastName) {
            return true;
        }
    }
})