AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

用過 Mongodb 吧, 這三個大坑踩過嗎?

來源: 責編: 時間:2023-10-26 17:12:16 241觀看
導讀一:背景1. 講故事前段時間有位朋友在微信群問,在向 mongodb 中插入的時間為啥取出來的時候少了 8 個小時,8 在時間處理上是一個非常敏感的數字,又吉利又是一個普適的話題,后來我想想初次使用 mongodb 的朋友一定還會遇到各

一:背景

1. 講故事

前段時間有位朋友在微信群問,在向 mongodb 中插入的時間為啥取出來的時候少了 8 個小時,8 在時間處理上是一個非常敏感的數字,又吉利又是一個普適的話題,后來我想想初次使用 mongodb 的朋友一定還會遇到各種新坑,比如說:插入的數據取不出來,看不爽的 ObjectID,時區不對等等,這篇就和大家一起聊一聊。91V28資訊網——每日最新資訊28at.com

二:1號坑 插進去的數據取不出來

1. 案例展示

這個問題是使用強類型操作 mongodb 你一定會遇到的問題,案例代碼如下:91V28資訊網——每日最新資訊28at.com

class Program    {        static void Main(string[] args)        {            var client = new MongoClient("mongodb://192.168.1.128:27017");            var database = client.GetDatabase("school");            var table = database.GetCollection<Student>("student");            table.InsertOne(new Student() { StudentName = "hxc", Created = DateTime.Now });            var query = table.AsQueryable().ToList();        }    }    public class Student    {        public string StudentName { get; set; }        public DateTime Created { get; set; }    }

圖片圖片91V28資訊網——每日最新資訊28at.com

我去,這么簡單的一個操作還報錯,要初學到放棄嗎?挺急的,在線等!91V28資訊網——每日最新資訊28at.com

2. 堆棧中深挖源碼

作為一個碼農還得有鉆研代碼的能力,從錯誤信息中看說有一個 _id 不匹配 student 中的任何一個字段,然后把全部堆棧找出來。91V28資訊網——每日最新資訊28at.com

System.FormatException  HResult=0x80131537  Message=Element '_id' does not match any field or property of class Newtonsoft.Test.Student.  Source=MongoDB.Driver  StackTrace:   at MongoDB.Driver.Linq.MongoQueryProviderImpl`1.Execute(Expression expression)   at MongoDB.Driver.Linq.MongoQueryableImpl`2.GetEnumerator()   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)   at Newtonsoft.Test.Program.Main(String[] args) in E:/crm/JsonNet/Newtonsoft.Test/Program.cs:line 32

接下來就用 dnspy 去定位一下 MongoQueryProviderImpl.Execute 到底干的啥,截圖如下:91V28資訊網——每日最新資訊28at.com

圖片圖片91V28資訊網——每日最新資訊28at.com

我去,這代碼硬核哈,用了 LambdaExpression 表達式樹,我們知道表達式樹用于將一個領域的查詢結構轉換為另一個領域的查詢結構,但要尋找如何構建這個方法體就比較耗時間了,接下來還是用 dnspy 去調試看看有沒有更深層次的堆棧。91V28資訊網——每日最新資訊28at.com

圖片圖片91V28資訊網——每日最新資訊28at.com

這個堆棧信息就非常清楚了,原來是在 MongoDB.Bson.Serialization.BsonClassMapSerializer.DeserializeClass 方法中出了問題,接下來找到問題代碼,簡化如下:91V28資訊網——每日最新資訊28at.com

public TClass DeserializeClass(BsonDeserializationContext context){    while (reader.ReadBsonType() != BsonType.EndOfDocument)    {        TrieNameDecoder<int> trieNameDecoder = new TrieNameDecoder<int>(elementTrie);        string text = reader.ReadName(trieNameDecoder);        if (trieNameDecoder.Found)        {            int value = trieNameDecoder.Value;            BsonMemberMap bsonMemberMap = allMemberMaps[value];        }        else        {            if (!this._classMap.IgnoreExtraElements)            {                throw new FormatException(string.Format("Element '{0}' does not match any field or property of class {1}.", text, this._classMap.ClassType.FullName));            }            reader.SkipValue();        }    }}

上面的代碼邏輯非常清楚,要么 student 中存在 _id 字段,也就是 trieNameDecoder.Found, 要么使用 忽略未知的元素,也就是 this._classMap.IgnoreExtraElements,添加字段容易,接下來看看怎么讓 IgnoreExtraElements = true,找了一圈源碼,發現這里是關鍵:91V28資訊網——每日最新資訊28at.com

圖片圖片91V28資訊網——每日最新資訊28at.com

也就是: foreach (IBsonClassMapAttribute bsonClassMapAttribute in classMap.ClassType.GetTypeInfo().GetCustomAttributes(false).OfType<IBsonClassMapAttribute>())這句話,這里的 classMap 就是 student,只有讓 foreach 得以執行才能有望 classMap.IgnoreExtraElements 賦值為 true ,接下來找找看在類上有沒有類似 IgnoreExtraElements 的 Attribute,嘿嘿,還真有一個類似的: BsonIgnoreExtraElements ,如下代碼:91V28資訊網——每日最新資訊28at.com

[BsonIgnoreExtraElements]    public class Student    {        public string StudentName { get; set; }        public DateTime Created { get; set; }    }

接下來執行一下代碼,可以看到問題搞定:91V28資訊網——每日最新資訊28at.com

圖片圖片91V28資訊網——每日最新資訊28at.com

如果你想驗證的話,可以繼續用 dnspy 去驗證一下源碼哈,如下代碼所示:91V28資訊網——每日最新資訊28at.com

圖片圖片91V28資訊網——每日最新資訊28at.com

接下來還有一種辦法就是增加 _id 字段,如果你不知道用什么類型接,那就用object就好啦,后續再改成真正的類型。91V28資訊網——每日最新資訊28at.com

圖片圖片91V28資訊網——每日最新資訊28at.com

三:2號坑 DateTime 時區不對

如果你細心的話,你會發現剛才案例中的 Created 時間是 2020/8/16 4:24:57, 大家請放心,我不會傻到凌晨4點還在寫代碼,好了哈,看看到底問題在哪吧, 可以先看看 mongodb 中的記錄數據,如下:91V28資訊網——每日最新資訊28at.com

{    "_id" : ObjectId("5f38b83e0351908eedac60c9"),    "StudentName" : "hxc",    "Created" : ISODate("2020-08-16T04:38:22.587Z")}

從 ISODate 可以看出,這是格林威治時間,按照0時區存儲,所以這個問題轉成了如何在獲取數據的時候,自動將 ISO 時間轉成 Local 時間就可以了,如果你看過底層源碼,你會發現在 mongodb 中每個實體的每個類型都有一個專門的 XXXSerializer,如下圖:91V28資訊網——每日最新資訊28at.com

圖片圖片91V28資訊網——每日最新資訊28at.com

接下來就好好研讀一下里面的 Deserialize 方法即可,代碼精簡后如下:91V28資訊網——每日最新資訊28at.com

public override DateTime Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args){    IBsonReader bsonReader = context.Reader;    BsonType currentBsonType = bsonReader.GetCurrentBsonType();    DateTime value;    switch (this._kind)    {        case DateTimeKind.Unspecified:        case DateTimeKind.Local:            value = DateTime.SpecifyKind(BsonUtils.ToLocalTime(value), this._kind);            break;        case DateTimeKind.Utc:            value = BsonUtils.ToUniversalTime(value);            break;    }    return value;}

可以看出,如果當前的 this._kind= DateTimeKind.Local 的話,就將 UTC 時間轉成 Local 時間,如果你有上一個坑的經驗,你大概就知道應該也是用特性注入的,91V28資訊網——每日最新資訊28at.com

[BsonDateTimeOptions(Kind = DateTimeKind.Local)]    public DateTime Created { get; set; }

不信的話,我調試給你看看哈。91V28資訊網——每日最新資訊28at.com

圖片圖片91V28資訊網——每日最新資訊28at.com

接下來再看看 this._kind 是怎么被賦的。91V28資訊網——每日最新資訊28at.com

圖片圖片91V28資訊網——每日最新資訊28at.com

圖片圖片91V28資訊網——每日最新資訊28at.com

四:3號坑 自定義ObjectID

在第一個坑中,不知道大家看沒看到類似這樣的語句: ObjectId("5f38b83e0351908eedac60c9") ,乍一看像是一個 GUID,當然肯定不是,這是mongodb自己組建了一個 number 組合的十六進制表示,姑且不說性能如何,反正看著不是很舒服,畢竟大家都習慣使用 int/long 類型展示的主鍵ID。91V28資訊網——每日最新資訊28at.com

那接下來的問題是:如何改成我自定義的 number ID 呢?當然可以,只要實現 IIdGenerator 接口即可,那主鍵ID的生成,我準備用 雪花算法,完整代碼如下:91V28資訊網——每日最新資訊28at.com

class Program    {        static void Main(string[] args)        {            var client = new MongoClient("mongodb://192.168.1.128:27017");            var database = client.GetDatabase("school");            var table = database.GetCollection<Student>("student");            table.InsertOne(new Student() { Created = DateTime.Now });            table.InsertOne(new Student() { Created = DateTime.Now });        }    }    class Student    {        [BsonId(IdGenerator = typeof(MyGenerator))]        public long ID { get; set; }        [BsonDateTimeOptions(Kind = DateTimeKind.Local)]        public DateTime Created { get; set; }    }    public class MyGenerator : IIdGenerator    {        private static readonly IdWorker worker = new IdWorker(1, 1);        public object GenerateId(object container, object document)        {            return worker.NextId();        }        public bool IsEmpty(object id)        {            return id == null || Convert.ToInt64(id) == 0;        }    }

然后去看一下 mongodb 生成的 json:91V28資訊網——每日最新資訊28at.com

圖片圖片91V28資訊網——每日最新資訊28at.com

四:總結

好了,這三個坑,我想很多剛接觸 mongodb 的朋友是一定會遇到的困惑,總結一下方便后人乘涼,結果不重要,重要的還是探索問題的思路和不擇手段

本文鏈接:http://www.tebozhan.com/showinfo-26-15228-0.html用過 Mongodb 吧, 這三個大坑踩過嗎?

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 如何保證分布式情況下的冪等性

下一篇: 狀態模式:對象狀態的變化,你學會了嗎?

標簽:
  • 熱門焦點
  • 六大權益!華為8月服務日開啟:手機免費貼膜、維修免人工費

    8月5日消息,一年一度的華為開發者大會2023(Together)日前在松山湖拉開帷幕,與此同時,華為8月服務日也式開啟,到店可享六大專屬權益。華為用戶可在華為商城Ap
  • Automa-通過連接塊來自動化你的瀏覽器

    1、前言通過瀏覽器插件可實現自動化腳本的錄制與編寫,具有代表性的工具就是:Selenium IDE、Katalon Recorder,對于簡單的業務來說可快速實現自動化的上手工作。Selenium IDEKat
  • 三言兩語說透設計模式的藝術-單例模式

    寫在前面單例模式是一種常用的軟件設計模式,它所創建的對象只有一個實例,且該實例易于被外界訪問。單例對象由于只有一個實例,所以它可以方便地被系統中的其他對象共享,從而減少
  • 使用AIGC工具提升安全工作效率

    在日常工作中,安全人員可能會涉及各種各樣的安全任務,包括但不限于:開發某些安全工具的插件,滿足自己特定的安全需求;自定義github搜索工具,快速查找所需的安全資料、漏洞poc、exp
  • 中國家電海外掘金正當時|出海專題

    作者|吳南南編輯|胡展嘉運營|陳佳慧出品|零態LT(ID:LingTai_LT)2023年,出海市場戰況空前,中國創業者在海外紛紛摩拳擦掌,以期能夠把中國的商業模式、創業理念、戰略打法輸出海外,他們依
  • 自律,給不了Keep自由!

    來源 | 互聯網品牌官作者 | 李大為編排 | 又耳 審核 | 谷曉輝自律能不能給用戶自由暫時不好說,但大概率不能給Keep自由。近日,全球最大的在線健身平臺Keep正式登陸港交所,努力
  • 騰訊VS網易,最卷游戲暑期檔,誰能笑到最后?

    作者:無銹缽來源:財經無忌7月16日晚,上海1862時尚藝術中心。伴隨著幻象的精準命中,碩大的熒幕之上,比分被定格在了14:12,被寄予厚望的EDG戰隊以絕對的優勢戰勝了BLG戰隊,拿下了總決
  • 華為發布HarmonyOS 4:更好玩、更流暢、更安全

    在8月4日的華為開發者大會2023(HDC.Together)大會上,HarmonyOS 4正式發布。自2019年發布以來,HarmonyOS一直以用戶為中心,經歷四年多的發展HarmonyOS已
  • 自研Exynos回歸!三星Galaxy S24系列將提供Exynos和驍龍雙版本

    年初,全新的三星Galaxy S23系列發布,包含Galaxy S23、Galaxy S23+和Galaxy S23 Ultra三個版本,全系搭載超頻版驍龍8 Gen 2,雖同樣采用臺積電4nm工藝制
Top