记一次Mongodb数据库更新操作之更新为数组或者对象
一直以来都是更新为一些简单的基础类型,直到有一天写了一个覆盖某一个字段(这个字段为数组)的更新操作。出问题了,数据库中出现了_t,_v……有点懵了。当然如果我们更新的时候设置类型是不会出现这个问题的,出现这种问题的一个前提是我们将数组赋值给了object类型的变量;由于时间关系问了一下同事,她给出了解决办法:mongodb的驱动去反序列化一下。问题就这么解决了,今天有时间记录一下,在写示例代码的时候发现更新对象也不行。
先看一下我们的数据,以及更新之后的截图:
/* 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命令,你会发现是这样的,
后面直接用同事的方法试了一下,再查看生成的语句就没问题了
既然updatedefinition可以转成字符串,并且他同样可以直接赋值为字符串,例如:updatedefinition<bsondocument> updatedefinition = ""; ,那么我想了一下我们直接拼这个字符串应该就没问题了,当然这种我没有测试啊!
这里面还会遇到一个问题就是怎么判断一个object的真实类型,这里仅仅需要知道他是不是对象或者数组(这里是泛指所有的)。可能真的有点菜,不知道如果判断。看了一下官方文档:type类,也没有找到,最后还是使用比较笨的方法:先序列化为字符串之后在反序列化为object,他会告诉你类型的。最后一个问题是这个解决问题的办法是不是最优的,感觉有点浪费……如果有哪位大神知道高效的方式,请不吝赐教,再次感谢。
最后看一下我的示例代码:
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() { // 这里也遇到了同样的问题 // 1、https://jira.mongodb.org/browse/csharp-1984 // 其他相关 // 1、https://www.codeproject.com/tips/1268019/mongodb-csharp-how-to-deserialize-a-json-containin // 2、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; } } }
上一篇: 十倍光学变焦到底有多强? 华为P40影像实力再破纪录
下一篇: 网络赚钱 美妆麻豆 网拍淘金日入千元