C# MongoDB:仅更新特定字段

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14853362/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 13:13:33  来源:igfitidea点击:

MongoDB: update only specific fields

c#mongodbmongodb-.net-driver

提问by Manny

I am trying to update a row in a (typed) MongoDB collection with the C# driver. When handling data of that particular collection of type MongoCollection<User>, I tend to avoid retrieving sensitive data from the collection (salt, password hash, etc.)

我正在尝试使用 C# 驱动程序更新(类型化)MongoDB 集合中的一行。在处理特定类型集合的数据时MongoCollection<User>,我倾向于避免从集合中检索敏感数据(salt、密码哈希等)。

Now I am trying to update a Userinstance. However, I never actually retrieved sensitive data in the first place, so I guess this data would be default(byte[])in the retrieved model instance (as far as I can tell) before I apply modifications and submit the new data to the collection.

现在我正在尝试更新一个User实例。但是,我从来没有真正检索过敏感数据,所以我猜default(byte[])在我应用修改并将新数据提交到集合之前,这些数据将在检索到的模型实例中(据我所知)。

Maybe I am overseeing something trivial in the MongoDB C# driver how I can use MongoCollection<T>.Save(T item)without updating specific properties such as User.PasswordHashor User.PasswordSalt? Should I retrieve the full record first, update "safe" properties there, and write it back? Or is there a fancy option to exclude certain fields from the update?

也许我正在 MongoDB C# 驱动程序中监督一些琐碎的事情,我如何在MongoCollection<T>.Save(T item)不更新特定属性的情况下使用,例如User.PasswordHashUser.PasswordSalt?我应该先检索完整记录,更新那里的“安全”属性,然后写回吗?或者是否有从更新中排除某些字段的奇特选项?

Thanks in advance

提前致谢

采纳答案by Nuk Nuk San

Save(someValue) is for the case where you want the resulting record to be or become the full object (someValue) you passed in.

Save(someValue) 适用于您希望结果记录成为或成为您传入的完整对象 (someValue) 的情况。

You can use

您可以使用

var query = Query.EQ("_id","123");
var sortBy = SortBy.Null;
var update = Update.Inc("LoginCount",1).Set("LastLogin",DateTime.UtcNow); // some update, you can chain a series of update commands here

MongoCollection<User>.FindAndModify(query,sortby,update); 

method.

方法。

Using FindAndModify you can specify exactly which fields in an existing record to change and leave the rest alone.

使用 FindAndModify,您可以准确地指定要更改现有记录中的哪些字段,其余字段则保持不变。

You can see an example here.

您可以在此处查看示例。

The only thing you need from the existing record would be its _id, the 2 secret fields need not be loaded or ever mapped back into your POCO object.

您从现有记录中唯一需要的是它的 _id,这 2 个秘密字段不需要加载或映射回您的 POCO 对象。

回答by user6356311

It′s possible to add more criterias in the Where-statement. Like this:

可以在 Where 语句中添加更多条件。像这样:

var db = ReferenceTreeDb.Database;
var packageCol = db.GetCollection<Package>("dotnetpackage");
var filter = Builders<Package>.Filter.Where(_ => _.packageName == packageItem.PackageName.ToLower() && _.isLatestVersion);
var update = Builders<Package>.Update.Set(_ => _.isLatestVersion, false);
var options = new FindOneAndUpdateOptions<Package>();
packageCol.FindOneAndUpdate(filter, update, options);

回答by Vikash Pandey

Well there are many ways to updated value in mongodb.

嗯,有很多方法可以更新mongodb.

Below is one of the simplest way I choose to update a field value in mongodb collection.

下面是我选择更新 mongodb 集合中字段值的最简单方法之一。

public string UpdateData()
        {               
            string data = string.Empty;
            string param= "{$set: { name:'Developerrr New' } }";
            string filter= "{ 'name' : 'Developerrr '}";
            try
            {  
               //******get connections values from web.config file*****
                var connectionString = ConfigurationManager.AppSettings["connectionString"];
                var databseName = ConfigurationManager.AppSettings["database"];
                var tableName = ConfigurationManager.AppSettings["table"];

                //******Connect to mongodb**********
                var client = new MongoClient(connectionString);
                var dataBases = client.GetDatabase(databseName);
                var dataCollection = dataBases.GetCollection<BsonDocument>(tableName);       

                //****** convert filter and updating value to BsonDocument*******
                BsonDocument filterDoc = BsonDocument.Parse(filter);
                BsonDocument document = BsonDocument.Parse(param);

                //********Update value using UpdateOne method*****
                dataCollection.UpdateOne(filterDoc, document);                   
                data = "Success";
            }
            catch (Exception err)
            {
                data = "Failed - " + err;
            }
            return data;    
        }

Hoping this will help you :)

希望这会帮助你:)

回答by Vitaly

Had the same problem and since I wanted to have 1 generic method for all types and didn't want to create my own implementation using Reflection, I end up with the following generic solution (simplified to show all in one method):

遇到了同样的问题,因为我想为所有类型使用 1 个通用方法,并且不想使用反射创建自己的实现,所以我最终得到了以下通用解决方案(简化为以一种方法显示所有内容):

Task<bool> Update(string Id, T item)
{
    var serializerSettings = new JsonSerializerSettings()
            {
                NullValueHandling = NullValueHandling.Ignore,
                DefaultValueHandling = DefaultValueHandling.Ignore
            };
    var bson = new BsonDocument() { { "$set", BsonDocument.Parse(JsonConvert.SerializeObject(item, serializerSettings)) } };
    await database.GetCollection<T>(collectionName).UpdateOneAsync(Builders<T>.Filter.Eq("Id", Id), bson);
}

Notes:

笔记:

  • Make sure all fields that must not update are set to default value.
  • If you need to set field to default value, you need to either use DefaultValueHandling.Include, or write custom method for that update
  • When performance matters, write custom update methods using Builders<T>.Update

    P.S.: It's obviously should have been implemented by MongoDB .Net Driver, however I couldn't find it anywhere in the docs, maybe I just looked the wrong way.

  • 确保所有不得更新的字段都设置为默认值。
  • 如果需要将字段设置为默认值,则需要使用 DefaultValueHandling.Include,或者为该更新编写自定义方法
  • 当性能很重要时,使用编写自定义更新方法 Builders<T>.Update

    PS:它显然应该由 MongoDB .Net Driver 实现,但是我在文档中的任何地方都找不到它,也许我只是看错了。