根据条件更新mongo集合

时间:2014-04-21 02:19:21

标签: node.js mongodb

我希望我的系统只有在用户被授权时才更新mongodb集合。我需要检查的信息在文档本身内。因此,我需要在实际更新集合之前进行评估。

mongo docs说:

  

“更新的选择标准。使用与find()方法中使用的相同的查询选择器。”

它指向了查询运算符$where

我的理解是,我能够使用文档本身的数据来决定文档是否得到更新。

我目前的做法如下:

db.myCollection.update( {
    criteriaA: 'A',
    $where: function() {
        // I expect this collection to update only when
        //  `current_user_is()` returns true
        return current_user_is( this.role );
    }, {
        $set: {
            criteriaB: 'B'
        }
    }
});

但显然,无论函数是否返回,都会插入文档。

澄清:

db.myCollection.update( {
    criteriaA: 'A',
    $where: function() {
        // I expect this to bail the update, but it won't
        return false;
    }, {
        $set: {
            criteriaB: 'B'
        }
    }
});

如何在不改变文档本身结构的情况下实现这种条件更新?我也试图避免事先查询文档(除非这是正确的方法)。

1 个答案:

答案 0 :(得分:1)

这不是正确的方法,原因有多种,但让我们从假设使用$where运算符开始。

$where的目的是在数据库服务器上执行JavaScript条件。文档会明确警告您使用它,因此通常使用它不是一个好主意。

唯一真正有效的理由,甚至应该避免使用.aggregate()方法,而是需要将文档中一个字段的值与另一个字段的值进行比较。

您要做的是执行一些很可能实际上不存在于数据库服务器上的代码。当然,出于您的意图,简单的做法就是检索当前用户的“角色”,然后针对您要更新的文档正常评估(并使用本机代码运算符而不是JavaScript)。或者以基本形式:

var currentRoles = getUserRolesSomeHow();

db.collection.update(
    {
        "criteriaA": "A",
        "role": { "$in": currentRoles }
    },
    {
        "$set": { "criteriaB": "B" }
    }
)    

这是有道理的,因为这些功能是“客户端”(如客户端到数据库)操作,并且实际上并未在服务器上执行。在那里获取您的信息并将其传递给您的查询。您的文档中明确包含“角色”信息,“角色”有权对其进行更新,因此只需正常使用即可。