7

我对 MongoDB 完全陌生......我缺少一个“新手”标签,所以专家不必看到这个问题。

我正在尝试使用表达式更新集合中的所有文档。我期望解决的查询是:

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

但是,这会导致以下错误消息:

ReferenceError: i_up 未定义 (shell):1

同时数据库吃这个也没问题:

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

我必须一次做一份文件吗?这似乎过于复杂。

更新 感谢 Sergio Tulentsev 告诉我它不起作用。现在,我真的很挣扎如何做到这一点。我向乐于助人的灵魂提供 500 个利润点,他们可以以 MongoDB 理解的方式编写此代码。如果您在我们的论坛上注册,我可以在那里将利润点添加到您的帐户中。

4

5 回答 5

6

我只是在搜索相当于 SQL 的 MongoDB 时遇到了这个问题:

update t
set c1 = c2
where ...

Sergio 是正确的,您不能在直接更新中引用另一个属性作为值。但是,db.c.find(...)返回一个游标,并且该游标有一个forEach方法

对 MongoDB 的查询返回一个游标,可以对其进行迭代以检索结果。查询的确切方式因语言驱动程序而异。下面的详细信息侧重于来自 MongoDB shell(即 mongo进程)的查询。

shellfind()方法返回一个游标对象,然后我们可以对其进行迭代以从结果中检索特定文档。我们 为此目的使用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 } }
        );
    });
})

其他语言应该类似。

于 2012-11-29T03:07:59.127 回答
5

您不能在更新中使用表达式。或者,您不能使用依赖于文档字段的表达式。简单的自包含数学表达式很好(例如2 * 2)。

如果要为所有文档设置一个新字段,该字段是其他字段的函数,则必须遍历它们并手动更新。多更新在这里无济于事。

于 2012-04-16T19:54:31.547 回答
3

Rha7 给出了一个好主意,但是如果不定义临时变量,上面的代码是行不通的。

此示例代码基于“生日”字段生成年龄(闰年)的近似计算,并将该值插入到所有不包含以下内容的文档的合适字段中:

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}});
});
于 2017-09-27T17:30:38.103 回答
2

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

于 2021-04-09T10:29:34.803 回答
0

从呼叫者 ID 的开头删除“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')
            }
        }
    )
});
于 2014-01-30T11:26:20.837 回答