在Mongodb中按字段乘以字段

时间:2011-12-01 14:14:25

标签: mongodb

我一直在寻找一种方法来创建一个更新语句,该语句将使用现有的数字字段并使用表达式对其进行修改。例如,如果我有一个名为Price的字段,是否可以进行将Price设置为现有值50%的更新?

所以,给定{ Price : 19.99 }

我想db.collection.update({tag : "refurb"}, {$set {Price : Price * 0.50 }}, false, true);

可以这样做,还是我必须将值读回客户端,修改,然后更新?我想问题就是可以在更新中使用表达式,并且它们可以引用正在更新的文档。

4 个答案:

答案 0 :(得分:37)

您可以使用db.eval()运行服务器端代码。

db.eval(function() { 
    db.collection.find({tag : "refurb"}).forEach(function(e) {
        e.Price = e.Price * 0.5;
        db.collection.save(e);
    });
});

请注意,这将阻止数据库,因此最好执行查找更新操作对。

请参阅https://docs.mongodb.com/manual/core/server-side-javascript/

答案 1 :(得分:21)

在新的 Mongo 2.6.x 中,有一个$mul operator。它会使用以下语法将字段的值乘以数字。

{
  $mul: { field: <number> }
}

因此,在您的情况下,您需要执行以下操作:

db.collection.update(
  { tag : "refurb"},
  { $mul: { Price : 0.5 } }
);

答案 2 :(得分:0)

from ctypes import * from defines import * from datetime import * import time kernel32 = windll.kernel32 class test(): def __init__(self): self.hProcess = None def load(self): creation_flags = CREATE_NEW_CONSOLE startupinfo = STARTUPINFO() process_information = PROCESS_INFORMATION() startupinfo.cb = sizeof(startupinfo) if kernel32.CreateProcessW('C:\\Windows\\System32\\calc.exe', None, None, None, None, creation_flags, None, None, byref(startupinfo), byref(process_information)): self.hProcess = process_information.hProcess print('CALC PID: {0}, Handle: {1}'.format(process_information.dwProcessId, process_information.hProcess)) else: print('Error while opening process') def waitfor(self): print(kernel32.WaitForSingleObject(self.hProcess, 0xFFFFFFFF)) s = test() s.load() s.waitfor() db.collection.update()开始可以接受聚合管道,最终允许基于另一个字段来更新一个字段:

Mongo 4.2
  • 第一部分// { price: 19.99 } // { price: 2.04 } db.collection.update( {}, [{ $set: { price: { $multiply: [ 0.5, "$price" ] } } }], { multi: true } ) // { price: 9.995 } // { price: 1.02 } 是匹配查询,用于过滤要更新的文档(在这种情况下为所有文档)。

  • 第二部分{}是更新聚合管道(请注意方括号表示使用聚合管道)。 $set是新的聚合运算符,别名为[{ $set: { price: ... } }]。注意如何$addFields根据其自身的值(price)直接进行修改。

  • 不要忘记$price,否则只会更新第一个匹配的文档。

答案 3 :(得分:-1)

嗯,这可以通过$ set进行原子操作。

您有几种选择:

  • 使用pingw33n提出的eval()解决方案
  • 检索要修改的文档以获取当前值并使用set
  • 进行修改
  • 如果您的操作率很高,您可能希望确保在获取其值时使用上一个解决方案时焦点没有改变,因此您可能希望使用findAndModify(请参阅this page灵感来自于如何做到这一点。操作。

这实际上取决于你的背景:对db的压力很小,我会选择pingw33n的解决方案。运行速度非常快,我会使用第三种解决方案。