在 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 12:20:42  来源:igfitidea点击:

Multiply field by value in Mongodb

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.2db.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). $setis a new aggregation operator and an alias of $addFields. Note how priceis 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 的解决方案。由于运行率非常高,我会使用第三种解决方案。