将字段乘以Mongodb中的值
我一直在寻找一种创建update语句的方法,该语句将接受现有的数字字段,并使用表达式对其进行修改。例如,如果我有一个名为Price的字段,是否可以进行更新,将Price设置为现有值的50% 因此,给定将字段乘以Mongodb中的值,mongodb,Mongodb,我一直在寻找一种创建update语句的方法,该语句将接受现有的数字字段,并使用表达式对其进行修改。例如,如果我有一个名为Price的字段,是否可以进行更新,将Price设置为现有值的50% 因此,给定{Price:19.99} 我想做db.collection.update({tag:“refurb”},{$set{Price:Price*0.50},false,true) 这是可以做到的,还是我必须将值读回客户机,修改,然后更新?我想接下来的问题是,表达式是否可以用于更新,以及它们是否可以引用
{Price:19.99}
我想做db.collection.update({tag:“refurb”},{$set{Price:Price*0.50},false,true)代码>
这是可以做到的,还是我必须将值读回客户机,修改,然后更新?我想接下来的问题是,表达式是否可以用于更新,以及它们是否可以引用正在更新的文档。您可以使用db.eval()
运行服务器端代码
注意,这将阻塞数据库,因此最好执行查找更新操作对
请参见好的,这在$set的原子操作中是可能的
您有几个选择:
- 使用pingw33n提出的eval()解决方案
- 检索要修改的文档以获取当前值,并使用集合修改它
- 如果您的操作率很高,您可能希望确保在获取其值的过程中焦点没有发生变化(使用以前的解决方案),因此您可能希望使用findAndModify(请参阅获取有关如何操作的灵感)操作
这实际上取决于您的上下文:由于数据库压力很低,我会选择pingw33n的解决方案。由于手术率很高,我会使用第三种解决方案。在新的Mongo2.6.x中有一个。它将使用以下语法将字段的值乘以数字
{
$mul: { field: <number> }
}
启动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 }
- 第一部分是匹配查询,过滤要更新的文档(本例中的所有文档)
- 第二部分是更新聚合管道(注意方括号表示使用聚合管道)。是一个新的聚合运算符,别名为
$addFields
。请注意,price
是如何根据其自身的值($price
)直接修改的
- 不要忘记
{multi:true}
,否则只会更新第一个匹配的文档
谢谢。你是说我应该像你所展示的那样使用eval(),还是应该在客户端使用find/update来避免阻塞?@Brad你应该评估这个特定更新操作的总体成本。如果操作很长(集合中的许多文档将被更新),则永远不要使用eval。首先查询一个文档,然后更新它,而不是就地更新,并没有太大的开销。特别是如果您限制查询大型文档的字段并使用covered index功能()很酷,谢谢。我还看到eval()不适用于切分,所以从长远来看,这排除了我的可能性。诺洛克是一个有趣的补充。这不是原子的。有关原子解决方案,请参见萨尔瓦多使用$mul
的答案。谢谢。我不知道findAndModify如何允许使用表达式,这是我的主要目标。@Brad findAndModify允许使用表达式,但它允许执行两个阶段的操作:首先获取项目,然后更新它(减少50%),前提是它自检索以来没有更改。请注意,在即将发布的mongo版本中,您可以在不使用所有这些eval和DB锁定的情况下完成这项工作,几乎不需要任何成本。检查并可能接受新答案,这样新开发人员就不会使用过时的信息。
db.collection.update(
{ tag : "refurb"},
{ $mul: { Price : 0.5 } }
);
// { price: 19.99 }
// { price: 2.04 }
db.collection.update(
{},
[{ $set: { price: { $multiply: [ 0.5, "$price" ] } } }],
{ multi: true }
)
// { price: 9.995 }
// { price: 1.02 }