在 Mongodb 中按值乘以字段
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8342725/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Multiply field by value in Mongodb
提问by Brad
I've been looking for a way to create an update statement that will take an existing numeric field and modify it using an expression. For example, if I have a field called Price, is it possible to do an update that sets Price to 50% off the existing value ?
我一直在寻找一种方法来创建更新语句,该语句将采用现有数字字段并使用表达式对其进行修改。例如,如果我有一个名为 Price 的字段,是否可以进行更新,将 Price 设置为现有值的 50% ?
So, given { Price : 19.99 }
所以,给定 { Price : 19.99 }
I'd like to do db.collection.update({tag : "refurb"}, {$set {Price : Price * 0.50 }}, false, true);
我想做 db.collection.update({tag : "refurb"}, {$set {Price : Price * 0.50 }}, false, true);
Can this be done or do I have to read the value back to the client, modify, then update ? I guess the question then is can expressions be used in update, and can they reference the document being updated.
这可以完成还是我必须将值读回客户端,修改,然后更新?我想问题是可以在更新中使用表达式,并且它们可以引用正在更新的文档。
回答by pingw33n
You can run server-side code with db.eval()
.
您可以使用db.eval()
.
db.eval(function() {
db.collection.find({tag : "refurb"}).forEach(function(e) {
e.Price = e.Price * 0.5;
db.collection.save(e);
});
});
Note this will block the DB, so it's better to do find-update operation pair.
注意这会阻塞数据库,所以最好做 find-update 操作对。
See https://docs.mongodb.com/manual/core/server-side-javascript/
请参阅https://docs.mongodb.com/manual/core/server-side-javascript/
回答by Salvador Dali
In the new Mongo 2.6.xthere is a $mul operator. It would multiply the value of the field by the number with the following syntax.
在新的Mongo 2.6.x 中有一个$mul 运算符。它将使用以下语法将字段的值乘以数字。
{
$mul: { field: <number> }
}
So in your case you will need to do the following:
因此,在您的情况下,您需要执行以下操作:
db.collection.update(
{ tag : "refurb"},
{ $mul: { Price : 0.5 } }
);
回答by Xavier Guihot
Starting Mongo 4.2
, db.collection.update()
can accept an aggregation pipeline, finally allowing the update of a field based on another field:
开始Mongo 4.2
,db.collection.update()
可以接受一个聚合管道,最后允许基于另一个字段更新一个字段:
// { price: 19.99 }
// { price: 2.04 }
db.collection.update(
{},
[{ $set: { price: { $multiply: [ 0.5, "$price" ] } } }],
{ multi: true }
)
// { price: 9.995 }
// { price: 1.02 }
The first part
{}
is the match query, filtering which documents to update (all documents in this case).The second part
[{ $set: { price: ... } }]
is the update aggregation pipeline (note the squared brackets signifying the use of an aggregation pipeline).$set
is a new aggregation operator and an alias of$addFields
. Note howprice
is modified directly based on the its own value ($price
).Don't forget
{ multi: true }
, otherwise only the first matching document will be updated.
第一部分
{}
是匹配查询,过滤要更新的文档(在本例中为所有文档)。第二部分
[{ $set: { price: ... } }]
是更新聚合管道(注意方括号表示使用聚合管道)。$set
是一个新的聚合运算符,是 的别名$addFields
。请注意如何price
直接根据其自身的值 ($price
) 进行修改。不要忘记
{ multi: true }
,否则只会更新第一个匹配的文档。
回答by kamaradclimber
Well, this is possible with an atomic operation as $set.
好吧,这可以通过 $set 的原子操作实现。
You have several options :
你有几个选择:
- use the eval() solution proposed by pingw33n
- retrieve the document you want to modify to get the current value and modify it with a set
- if you have a high operation rate, you might want to be sure the focument has not changed during you fetch its value (using the previous solution) so you might want to use a findAndModify (see this pageto get inspired on how to do it) operation.
- 使用 pingw33n 提出的 eval() 解决方案
- 检索要修改的文档以获取当前值并使用集合进行修改
- 如果您的操作率很高,您可能希望确保在获取其值期间焦点没有改变(使用以前的解决方案),因此您可能需要使用 findAndModify(请参阅此页面以获取有关如何操作的灵感) ) 手术。
It really depends on your context : with a very low pressure on the db, I'd go for the solution of pingw33n. With a very high operation rate, I'd use the third solution.
这真的取决于你的上下文:数据库的压力非常低,我会去寻找 pingw33n 的解决方案。由于运行率非常高,我会使用第三种解决方案。