MongoDB - 如果BsonDocument C上没有更新字段或添加字段#

时间:2018-02-08 23:29:16

标签: c# mongodb mongodb-query mongodb-.net-driver

我正在尝试将提供给API的任何JSON存储到BsonDocument中,这是使用C#驱动程序的另一个文档上的字段

但是,当我尝试使用UpdateOne方法时,它只是用我提交的内容替换文档。这是我的顶级mongo文档

public class SomeMongoDocument 
{
    public ObjectId _id { get; set; }

    public string FileName { get; set; }

    public BsonDocument Metadata { get; set; }
}

我想最初设置Metadata属性,然后稍后更新,更新可能不包含发送的所有初始元数据。所以当我尝试用这个来更新文档时:

public void UpdateMetadata(string filename, string metadata)
{
        var filter = Builders<SomeMongoDocument>.Filter.Eq(e => e.FileName, filename;

        BsonDocument document = BsonSerializer.Deserialize<BsonDocument>(metadata);

        var update = Builders<SomeMongoDocument>.Update.Set(e => e.Metadata, document);

        this.MongoCollection.UpdateOne(filter, update);

}

它只是覆盖BsonDocument并删除当我将其转换为bson文档时字符串中不存在的属性。

那么我该怎么做呢:

更新现有属性,或者在添加新属性时,保留已存在的属性。感谢

1 个答案:

答案 0 :(得分:2)

{ $set: { "metadata": { ... } } }替换整个metadata嵌入文档。如果要替换嵌入文档中的值,则应在$set运算符中指定它们,如:

{$ set:{&#34; metadata.innerField1&#34;:&#34; SomeValue1&#34;,&#34; metadata.innerField2&#34;:&#34; SomeValue2&#34; }

或使用MongoDB .Net驱动程序:

Builders<SomeMongoDocument>.Update
    .Set(e => e.Metadata.InnerField1, document.InnerField1)
    .Set(e => e.Metadata.InnerField2, document.InnerField2)
    // ...

由于您在文档中没有预定义的属性,因此您无法以这种方式在代码中对其进行硬编码。在这种情况下,您只需枚举BsonDocument元素并将其添加到更新定义:

UpdateDefinition<SomeMongoDocument> update = null;
foreach (BsonElement element in document)
{
    update = update?.Set(e => e.Metadata[element.Name], element.Value) ??
                Builders<SomeMongoDocument>.Update.Set(e => e.Metadata[element.Name], element.Value);
}

if (update != null)
{
    this.MongoCollection.UpdateOne(filter, update);
}