一直以來都是更新爲一些簡單的基礎類型,直到有一天寫了一個覆蓋某一個字段(這個字段爲數組)的更新操做。出問題了,數據庫中出現了_t,_v……有點懵了。固然若是咱們更新的時候設置類型是不會出現這個問題的,出現這種問題的一個前提是咱們將數組賦值給了object類型的變量;因爲時間關係問了一下同事,她給出瞭解決辦法:mongodb的驅動去反序列化一下。問題就這麼解決了,今天有時間記錄一下,在寫示例代碼的時候發現更新對象也不行。mongodb
先看一下咱們的數據,以及更新以後的截圖:shell
/* 1 */ { "_id" : "1", "Name" : "ddz001", "Age" : 10, "Valid" : true, "CreateDate" : ISODate("2020-03-28T05:59:43.841Z"), "LastUpdatedTime" : ISODate("2020-03-28T05:59:43.841Z"), "Details" : { "Height" : 169.5, "Weight" : 70.5, "Married" : true }, "Bookmarks" : [ { "Title" : "百度一下", "Url" : "https://www.baidu.com/" }, { "Title" : "必應", "Url" : "https://cn.bing.com/" } ] } /* 2 */ { "_id" : "2", "Name" : "ddz002", "Age" : 20, "Valid" : true, "CreateDate" : ISODate("2020-03-28T05:59:43.841Z"), "LastUpdatedTime" : ISODate("2020-03-28T05:59:43.841Z"), "Details" : { "Height" : 170.5, "Weight" : 71.5, "Married" : true }, "Bookmarks" : [ { "Title" : "搜狗搜索", "Url" : "https://www.baidu.com/" }, { "Title" : "多吉搜索", "Url" : "https://www.dogedoge.com/" } ] }
爲何會出現上圖中的問題,打印了一下UpdateDefinition生成的shell命令,你會發現是這樣的,數據庫
後面直接用同事的方法試了一下,再查看生成的語句就沒問題了json
既然UpdateDefinition能夠轉成字符串,而且他一樣能夠直接賦值爲字符串,例如:UpdateDefinition<BsonDocument> updateDefinition = ""; ,那麼我想了一下咱們直接拼這個字符串應該就沒問題了,固然這種我沒有測試啊!api
這裏面還會遇到一個問題就是怎麼判斷一個object的真實類型,這裏僅僅須要知道他是否是對象或者數組(這裏是泛指全部的)。可能真的有點菜,不知道若是判斷。看了一下官方文檔:Type類,也沒有找到,最後仍是使用比較笨的方法:先序列化爲字符串以後在反序列化爲object,他會告訴你類型的。最後一個問題是這個解決問題的辦法是否是最優的,感受有點浪費……若是有哪位大神知道高效的方式,請不吝賜教,再次感謝。數組
最後看一下個人示例代碼:ide
using MongoDB.Bson; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Attributes; using MongoDB.Driver; using System; using System.Collections.Generic; using System.Linq; using System.Text.Encodings.Web; using System.Text.Json; namespace DDZ.MongodbUpdateArrayTest { class Program { static void Main(string[] args) { //清空表(新增以前先清空)、批量添加(初始化一些數據)、查詢操做 //DeleteManyBatchAddFind(); //更新數據和Object測試 //UpdateArrayOrObject(); #region 尋找解決辦法 var _client = new MongoClient("mongodb://localhost:27017"); var _database = _client.GetDatabase("FormBuilder"); var _collection = _database.GetCollection<BsonDocument>("UpdateArrayTest"); DateTime dtNow2 = DateTime.Now; List<KeyValueModel> keyValueModels = new List<KeyValueModel>() { new KeyValueModel(){ Key="Name",Value ="ddz001+++" }, new KeyValueModel(){ Key="Age",Value = 11 }, new KeyValueModel(){ Key="Valid",Value = false }, new KeyValueModel(){ Key="LastUpdatedTime",Value=dtNow2 }, new KeyValueModel(){ Key="Details",Value = new OtherInfoModel(){ Height=179.5f,Weight=80.5f,Married=false } }, new KeyValueModel() { Key="Bookmarks",Value = new List<BookmarkModel>() { new BookmarkModel() { Title="Yandex",Url="https://yandex.com/" }, new BookmarkModel() { Title="祕跡搜索",Url="https://mijisou.com/" } } } }; var tempUpdateObj = new { Name = "ddz001+++", Age = 11, Valid = false, LastUpdatedTime = dtNow2, Details = new OtherInfoModel() { Height = 179.5f, Weight = 80.5f, Married = false }, Bookmarks = new List<BookmarkModel>() { new BookmarkModel() { Title="Yandex",Url="https://yandex.com/" }, new BookmarkModel() { Title="祕跡搜索",Url="https://mijisou.com/" } } }; var tempUpdateDic = new Dictionary<string, object>() { { "Name", "ddz001+++"}, { "Age", ""}, { "Valid", false}, { "LastUpdatedTime", dtNow2}, { "Details", new OtherInfoModel() { Height = 179.5f, Weight = 80.5f, Married = false }}, { "Bookmarks", new List<BookmarkModel>() { new BookmarkModel() { Title="Yandex",Url="https://yandex.com/" }, new BookmarkModel() { Title="祕跡搜索",Url="https://mijisou.com/" } } }, }; if (keyValueModels.Any()) { var updateDefinitions = new List<UpdateDefinition<BsonDocument>>(); foreach (var item in keyValueModels) { if (item.Value == null) { updateDefinitions.Add(Builders<BsonDocument>.Update.Set(item.Key, BsonNull.Value)); continue; } string tempValueForStr = JsonSerializer.Serialize(item.Value); var tempValueForObj = JsonSerializer.Deserialize<object>(tempValueForStr); var tempValueType = ((JsonElement)tempValueForObj).ValueKind; switch (tempValueType) { case JsonValueKind.Object: case JsonValueKind.Array: { updateDefinitions.Add(Builders<BsonDocument>.Update.Set(item.Key, BsonSerializer.Deserialize<object>(tempValueForStr))); break; } default: { updateDefinitions.Add(Builders<BsonDocument>.Update.Set(item.Key, item.Value)); break; } } } var updateDefinition = Builders<BsonDocument>.Update.Combine(updateDefinitions); string tempUpdateStr = GetJsonStingByUpdateDefinition(updateDefinition); //var modifiedCount1 = _collection.UpdateMany(Builders<BsonDocument>.Filter.Eq("_id", "1"), updateDefinition).ModifiedCount; string tempUpdateStrFromObj = "{ \"$set\" : " + tempUpdateObj.ToJson() + " }"; //你會發現這個字符串中也是包含_t和_v,由於字典的值類型爲object //驅動可能也是這麼調用的,固然我沒看源碼 string tempUpdateStrFromDictionary = "{ \"$set\" : " + tempUpdateDic.ToJson() + " }"; //var modifiedCount2 = _collection.UpdateMany(Builders<BsonDocument>.Filter.Eq("_id", "1"), tempUpdateStrFromObj).ModifiedCount; } #endregion Console.WriteLine("Hello World!"); } /// <summary> /// 清空表(新增以前先清空)、批量添加(初始化一些數據)、查詢操做 /// </summary> static void DeleteManyBatchAddFind() { var _client = new MongoClient("mongodb://localhost:27017"); var _database = _client.GetDatabase("FormBuilder"); var _collection = _database.GetCollection<UpdateArrayTestModel>("UpdateArrayTest"); // 若是表不存在不報錯 var delCount = _collection.DeleteMany(Builders<UpdateArrayTestModel>.Filter.Empty).DeletedCount; var dtNow = DateTime.Now; List<UpdateArrayTestModel> initUpdateArrayTestModels = new List<UpdateArrayTestModel>() { new UpdateArrayTestModel() { Id="1",Name="ddz001",Age=10,Valid=true,CreateDate=dtNow,LastUpdatedTime=dtNow, Details=new OtherInfoModel(){ Height=169.5f, Weight=70.5f, Married=true }, Bookmarks=new List<BookmarkModel>() { new BookmarkModel(){ Title="百度一下",Url="https://www.baidu.com/" }, new BookmarkModel(){ Title="必應",Url="https://cn.bing.com/" } } }, new UpdateArrayTestModel() { Id="2",Name="ddz002",Age=20,Valid=true,CreateDate=dtNow,LastUpdatedTime=dtNow, Details=new OtherInfoModel(){ Height=170.5f, Weight=71.5f, Married=true }, Bookmarks=new List<BookmarkModel>() { new BookmarkModel(){ Title="搜狗搜索",Url="https://www.baidu.com/" }, new BookmarkModel(){ Title="多吉搜索",Url="https://www.dogedoge.com/" } } } }; _collection.InsertMany(initUpdateArrayTestModels); //這裏的中文尚未問題 var queryResult = _collection.Find(Builders<UpdateArrayTestModel>.Filter.Empty).ToList(); //這裏的中文就變成了unicode,你能夠試一試序列化選項 var queryResultStr = JsonSerializer.Serialize(queryResult); JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions{ Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping }; var queryResultStr2 = JsonSerializer.Serialize(queryResult, jsonSerializerOptions); } /// <summary> /// 更新數據和Object測試 /// </summary> static void UpdateArrayOrObject() { // 這裏也遇到了一樣的問題 // 一、https://jira.mongodb.org/browse/CSHARP-1984 // 其餘相關 // 一、https://www.codeproject.com/Tips/1268019/MongoDB-Csharp-How-to-Deserialize-a-JSON-Containin // 二、https://blog.csdn.net/mzl87/article/details/85488319 var _client = new MongoClient("mongodb://localhost:27017"); var _database = _client.GetDatabase("FormBuilder"); var _collection = _database.GetCollection<BsonDocument>("UpdateArrayTest"); List<KeyValueModel> keyValueModels = new List<KeyValueModel>() { new KeyValueModel(){ Key="Name",Value ="ddz001+++" }, new KeyValueModel(){ Key="Age",Value = 11 }, new KeyValueModel(){ Key="Valid",Value = false }, new KeyValueModel(){ Key="LastUpdatedTime",Value=DateTime.Now }, new KeyValueModel(){ Key="Details",Value= new OtherInfoModel(){ Height=179.5f,Weight=80.5f,Married=false } }, new KeyValueModel() { Key="Bookmarks",Value = new List<BookmarkModel>() { new BookmarkModel() { Title="Yandex",Url="https://yandex.com/" }, new BookmarkModel() { Title="祕跡搜索",Url="https://mijisou.com/" } } } }; if (keyValueModels.Any()) { var updateDefinitions = new List<UpdateDefinition<BsonDocument>>(); foreach (var item in keyValueModels) { updateDefinitions.Add(Builders<BsonDocument>.Update.Set(item.Key, item.Value)); } var updateDefinition = Builders<BsonDocument>.Update.Combine(updateDefinitions); string tempUpdateStr = GetJsonStingByUpdateDefinition(updateDefinition); //var modifiedCount = _collection.UpdateMany(Builders<BsonDocument>.Filter.Eq("_id", "1"), updateDefinition).ModifiedCount; } } /// <summary> /// 將UpdateDefinition轉爲shell字符串 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="updateDefinition"></param> /// <returns></returns> static string GetJsonStingByUpdateDefinition<T>(UpdateDefinition<T> updateDefinition) { // 參考網址: // https://qa.1r1g.com/sf/ask/2243338471/ if (updateDefinition == null) return null; //updateDefinition.Render(_collection.DocumentSerializer,_collection.Settings.SerializerRegistry).ToString() return updateDefinition.Render(BsonSerializer.SerializerRegistry.GetSerializer<T>(), BsonSerializer.SerializerRegistry).ToString(); } } public class UpdateArrayTestModel { private string _id { get; set; } /// <summary> /// 主鍵ID /// </summary> public string Id { set => this._id = value; get => _id; } /// <summary> /// 姓名 /// </summary> public string Name { get; set; } /// <summary> /// 年齡 /// </summary> public int Age { get; set; } /// <summary> /// 是否有效 /// </summary> public bool Valid { get; set; } = true; /// <summary> /// 建立時間 /// </summary> [BsonDateTimeOptions(Kind = DateTimeKind.Unspecified)] public DateTime CreateDate { get; set; } /// <summary> /// 最後一次更新時間 /// </summary> [BsonDateTimeOptions(Kind = DateTimeKind.Unspecified)] public DateTime LastUpdatedTime { get; set; } /// <summary> /// 其餘詳細信息 /// </summary> public OtherInfoModel Details { get; set; } /// <summary> /// 個人書籤 /// </summary> public IEnumerable<BookmarkModel> Bookmarks { get; set; } } public class OtherInfoModel { public float Height { get; set; } public float Weight { get; set; } public bool Married { get; set; } = true; } public class BookmarkModel { public string Title { get; set; } public string Url { get; set; } } public class KeyValueModel { public string Key { get; set; } public object Value { get; set; } } }