我们应该多久使用MongoDB的运营商

时间:2015-08-24 11:48:32

标签: mongodb mongodb-query

我有这个特殊情况,我必须根据同一文档中存在的不同属性更新MongoDB中的某些值。所以我试图将findAndUpdate用于将传递JavaScript函数的where运算符,我也将使用其中一个属性作为查找条件。但是在MongoDB文档中已经提到过,在由于性能问题而无法避免之前,不应该使用where运算符。

现在假设我的文档中有3个属性id,counter1,counter2,我只在counter1 + counter2 = 2时将counter1更新为1。所以我会写一些像

这样的东西
db.mydb.findAndUpdate({"_id" : id, $where : function() { 
                                   this.counter1 + this.counter2 == 2 ;}}, 
                      {$inc : {counter1 : 1}})

现在我的问题是:

  1. 这种特殊方法是否会产生任何性能问题?因为我使用id作为搜索文档的另一个非运营商标准。
  2. 或者我应该在mydb集合中有另一个属性叫做sumCounter,它将存储counter1和counter2的值。

1 个答案:

答案 0 :(得分:2)

因此$where评估的主要问题是条件逻辑无法处理“索引”以过滤匹配。此外,它毕竟是JavaScript逻辑,需要进行编译,并且需要从本机表单中进行“对象转换”,以便与JavacScript引擎中的评估一起使用。

所以它的使用应该“非常谨慎”,并且只有在“绝对”需要的时候,因为没有其他实用的方法。在你的情况下,这是一个“更新”操作,因此如果你需要那个逻辑那么好。如果它只是一个“查询”,那么我会说在聚合框架中使用$redact代替:

db.mydb.aggregate([
    { "$match": { "_id": id } } },
    { "$redact": {
        "$cond": {
            "if": {
                "$eq": [
                    { "$add": [ "$counter1", "$counter2" ] },
                    2
                ]
            },
            "then": "$$KEEP",
            "else": "$$PRUNE"
        }
    }}        
])

因为这至少在本地运营商中都是如此,因此比JavaScript工作得更快。

至于“表现”,那都是相对的。但是,在_id是“唯一”查找的情况下,实际性能“命中”应该可以忽略不计,因为已经对主键的“索引”进行了“完全匹配”。

这是$where条件的一般建议。在那里你通常与其他本地查询运算符一起“使用它们”,这些运算符执行过滤的“批量”。然后,如果在JavaScript逻辑中应用条件需要更多的CPU周期(并且由于没有其他方法,它是绝对需要的),那么就这样吧。

但是,如果您的基于JavaScript的条件需要在没有其他过滤的帮助下扫描许多文档,那么这确实很糟糕。