当前位置: 移动技术网 > IT编程>开发语言>c# > 记一次Mongodb数据库更新操作之更新为数组或者对象

记一次Mongodb数据库更新操作之更新为数组或者对象

2020年03月30日  | 移动技术网IT编程  | 我要评论
一直以来都是更新为一些简单的基础类型,直到有一天写了一个覆盖某一个字段(这个字段为数组)的更新操作。出问题了,数据库中出现了_t,_v……有点懵了。当然如果我们更新的时候设置类型是不会出现这个问题的,出现这种问题的一个前提是我们将数组赋值给了object类型的变量;由于时间关系问了一下同事,她给出了 ...

  一直以来都是更新为一些简单的基础类型,直到有一天写了一个覆盖某一个字段(这个字段为数组)的更新操作。出问题了,数据库中出现了_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; }
    }
}

 

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网