我一直在寻找一种方法来创建一个更新语句,该语句将使用现有的数字字段并使用表达式对其进行修改。例如,如果我有一个名为Price的字段,是否可以进行将Price设置为现有值50%的更新?
所以,给定{ Price : 19.99 }
我想db.collection.update({tag : "refurb"}, {$set {Price : Price * 0.50 }}, false, true);
可以这样做,还是我必须将值读回客户端,修改,然后更新?我想问题就是可以在更新中使用表达式,并且它们可以引用正在更新的文档。
答案 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进行原子操作。
您有几种选择:
这实际上取决于你的背景:对db的压力很小,我会选择pingw33n的解决方案。运行速度非常快,我会使用第三种解决方案。