使用另一个字段的值更新MongoDB字段

537
在 MongoDB 中,是否可以使用另一个字段的值更新一个字段的值?相当于 SQL 中的某些语句:
UPDATE Person SET Name = FirstName + ' ' + LastName

而 MongoDB 的伪代码则是:

db.person.update( {}, { $set : { name : firstName + ' ' + lastName } );

花括号不匹配...如果我让它工作,我会纠正它。 - wojand
12个回答

0
(我本来想把这个作为评论发布的,但是不行)
对于任何试图使用C#驱动程序更新文档中的一个字段并使用另一个字段的人...
我无法弄清如何使用任何UpdateXXX方法及其相关重载,因为它们将UpdateDefinition作为参数。
// we want to set Prop1 to Prop2
class Foo { public string Prop1 { get; set; } public string Prop2 { get; set;} } 

void Test()
{ 
     var update = new UpdateDefinitionBuilder<Foo>();
     update.Set(x => x.Prop1, <new value; no way to get a hold of the object that I can find>)
}

作为一种解决方法,我发现您可以在IMongoDatabase上使用RunCommand方法(https://docs.mongodb.com/manual/reference/command/update/#dbcmd.update)。
var command = new BsonDocument
        {
            { "update", "CollectionToUpdate" },
            { "updates", new BsonArray 
                 { 
                       new BsonDocument
                       {
                            // Any filter; here the check is if Prop1 does not exist
                            { "q", new BsonDocument{ ["Prop1"] = new BsonDocument("$exists", false) }}, 
                            // set it to the value of Prop2
                            { "u", new BsonArray { new BsonDocument { ["$set"] = new BsonDocument("Prop1", "$Prop2") }}},
                            { "multi", true }
                       }
                 }
            }
        };

 database.RunCommand<BsonDocument>(command);

0

使用 MongoDB 版本 4.2+,更新更加灵活,因为它允许在其 updateupdateOneupdateMany 中使用聚合管道。现在可以使用聚合操作符转换文档,然后进行更新,而无需显式声明 $set 命令(而是使用 $replaceRoot: {newRoot: "$$ROOT"}

在此示例中,我们使用聚合查询从 MongoDB 的 ObjectID "_id" 字段中提取时间戳,并更新文档(我不是 SQL 方面的专家,但我认为 SQL 不提供任何带有时间戳的自动生成 ObjectID,您需要自动创建该日期)

var collection = "person"

agg_query = [
    {
        "$addFields" : {
            "_last_updated" : {
                "$toDate" : "$_id"
            }
        }
    },
    {
        $replaceRoot: {
            newRoot: "$$ROOT"
        } 
    }
]

db.getCollection(collection).updateMany({}, agg_query, {upsert: true})

1
你不需要使用 { $replaceRoot: { newRoot: "$$ROOT" } };这意味着用自身替换文档,这是没有意义的。如果你将 $addFields 替换为它的别名 $set,并且将 updateMany 替换为 update 的其中一个别名,则可以得到与 此答案 完全相同的答案。 - Xavier Guihot
感谢@Xavier Guihot的评论。使用$replaceRoot的原因是因为我们需要使用$toDate查询,而$set不提供使用$toDate的方法。 - Yi Xiang Chong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接