mongodb 用表达式而不是值更新

llmtgqce  于 2023-03-01  发布在  Go
关注(0)|答案(6)|浏览(108)

我是MongoDB的新手...我缺少了一个"新手"标签,所以Maven们不会看到这个问题。
我正在尝试使用表达式更新集合中的所有文档。我希望解决此问题的查询是:

db.QUESTIONS.update({}, { $set: { i_pp : i_up * 100 - i_down * 20 } }, false, true);

但是,这会导致以下错误消息:
参考错误:i_up未定义(shell):1
同时,数据库也没有发现吃这一条有什么问题:

db.QUESTIONS.update({}, { $set: { i_pp : 0 } }, false, true);

我必须一次做一个文档还是什么?那看起来太复杂了。

    • 更新**谢谢Sergio Tulentsev告诉我它不起作用。现在,我真的很纠结于如何做到这一点。我提供500 Profit Points给乐于助人的灵魂,谁可以写MongoDB理解的方式。如果你在our forum上注册,我可以添加利润点到您的帐户那里。
ehxuflar

ehxuflar1#

我在搜索MongoDB中的SQL等价物时遇到了这个问题,如下所示:

update t
set c1 = c2
where ...

Sergio是正确的,在直接更新中不能引用另一个属性作为值。但是,db.c.find(...)返回cursor and that cursor has a forEach method
对MongoDB的查询返回一个游标,它可以被迭代以检索结果。查询的确切方式将随语言驱动程序而变化。下面的详细信息集中在来自MongoDB shell(即mongo进程)的查询上。
shell的find()方法返回一个cursor对象,然后我们可以通过迭代从结果中检索特定的文档,为此我们使用hasNext()next()方法。

for( var c = db.parts.find(); c.hasNext(); ) {
   print( c.next());
}

此外,在shell中,forEach()可以与游标一起使用:

db.users.find().forEach( function(u) { print("user: " + u.name); } );

所以你可以这样说:

db.QUESTIONS.find({}, {_id: true, i_up: true, i_down: true}).forEach(function(q) {
    db.QUESTIONS.update(
        { _id: q._id },
        { $set: { i_pp: q.i_up * 100 - q.i_down * 20 } }
    );
});

一次更新一个而不离开MongoDB。
如果您使用驱动程序连接到MongoDB,那么应该有某种方法将JavaScript字符串发送到MongoDB;例如,对于Ruby驱动程序,您可以使用eval

connection.eval(%q{
    db.QUESTIONS.find({}, {_id: true, i_up: true, i_down: true}).forEach(function(q) {
        db.QUESTIONS.update(
            { _id: q._id },
            { $set: { i_pp: q.i_up * 100 - q.i_down * 20 } }
        );
    });
})

其他语言应该类似。

20jt8wwn

20jt8wwn2#

//the only differnce is to make it look like and aggregation pipeline
db.table.updateMany({}, [{
      $set: {
        col3:{"$sum":["$col1","$col2"]}
      },
    }]
 )
q43xntqr

q43xntqr3#

你不能在更新中使用表达式。或者说,你不能使用依赖于文档字段的表达式。简单的自包含数学表达式就可以了(例如2 * 2)。
如果你想为所有的文档设置一个新的字段,这个新字段是其他字段的函数,你必须遍历这些字段并手动更新。

n8ghc7c1

n8ghc7c14#

Rha7给出了一个好主意,但是上面的代码在没有定义临时变量的情况下无法工作。
此示例代码基于“birthday”字段生成年龄(场景后面的闰年)的近似计算,并将值插入到所有不包含以下内容的文档的适当字段中:

db.employers.find({age: {$exists: false}}).forEach(function(doc){
    var new_age = parseInt((ISODate() - doc.birthday)/(3600*1000*24*365));
    db.employers.update({_id: doc._id}, {$set: {age: new_age}});
});
2g32fytz

2g32fytz5#

删除来电显示开头的“00”示例:

db.call_detail_records_201312.find(
    { destination: /^001/ }, 
    { "destination": true }
).forEach(function(row){
    db.call_detail_records_201312.update(
        { _id: row["_id"] },
        { $set: {
                destination: row["destination"].replace(/^001/, '1')
            }
        }
    )
});
b5buobof

b5buobof6#

我在另一个问题上做了一个类似这样的自引用文档表达式:

db.activities.find().forEach((row)=> { 
  db.activities.updateOne({
    _id: row._id
  }, {
    $set: {
      cost: row.cost * 1.35
    }
  });
  })

在Atlas免费层上,这需要很长时间才能执行,更新速率约为每秒35次

相关问题