In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces whether you have stepped on the three big pits of mongodb, the content is very detailed, interested friends can refer to it, hope to be helpful to you.
One: background 1. Tell a story
Some time ago, a friend in the Wechat group asked why the time inserted into mongodb was taken out by 8 hours. 8 is a very sensitive number in time processing, and auspicious is also a universal topic. Later, I thought that friends who use mongodb for the first time must also encounter all kinds of new pits, such as: the inserted data cannot be pulled out, the ObjectID is not satisfied, the time zone is not right, and so on. I'll just have a chat with you in this article.
Two: the data inserted in pit 1 cannot be taken out. Case presentation
This problem is a problem that you will definitely encounter when using strong typing to operate mongodb. The case code is as follows:
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"); 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;}}
I'll go, such a simple operation also reported an error, do you want to learn to give up? I'm in a hurry, wait online!
two。 Dig deep into the source code in the stack
As a programmer, you also have to have the ability to delve into the code, look at the error message that a _ id does not match any of the fields in the student, and then find the entire stack.
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.Collection s.Generic.List`1.. 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
Next, use dnspy to locate what MongoQueryProviderImpl.Execute is doing. The screenshot is as follows:
I go, this code hard core ha, using the LambdaExpression expression tree, we know that the expression tree is used to transform one domain query structure into another domain query structure, but to find out how to build this method body is more time-consuming, and then use dnspy to debug to see if there is a deeper stack.
The stack information is very clear. It turns out that there is a problem in the MongoDB.Bson.Serialization.BsonClassMapSerializer.DeserializeClass method. Next, find the problem code and simplify it as follows:
Public TClass DeserializeClass (BsonDeserializationContext context) {while (reader.ReadBsonType ()! = BsonType.EndOfDocument) {TrieNameDecoder trieNameDecoder = new TrieNameDecoder (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 ();}
The logic of the above code is very clear. Either there is a _ id field in student, that is, trieNameDecoder.Found, or ignore unknown elements, that is, this._classMap.IgnoreExtraElements. It is easy to add fields. Next, look at how to make IgnoreExtraElements = true, find a circle of source code, and find that this is the key:
That is: foreach (IBsonClassMapAttribute bsonClassMapAttribute in classMap.ClassType.GetTypeInfo (). GetCustomAttributes (false). OfType ()), the classMap here is student, and only when foreach is executed can it be expected that classMap.IgnoreExtraElements can be assigned to true. Then find out if there is an Attribute similar to IgnoreExtraElements on the class. Heh heh, there is really a similar one: BsonIgnoreExtraElements, the following code:
[BsonIgnoreExtraElements] public class Student {public string StudentName {get; set;} public DateTime Created {get; set;}}
Next, execute the code, and you can see that the problem is solved:
If you want to verify, you can continue to use dnspy to verify the source code, as shown in the following code:
Another way is to add the _ id field. If you don't know what type to use, just use object and change it to the real type later.
3: pit 2 DateTime time zone is not correct
If you are careful, you will find that the Created time in the case just now is 4:24:57 on 2020-8-16. Please rest assured that I will not be foolish enough to be writing code at 4: 00 in the morning. OK, let's see what the problem is. You can first take a look at the recorded data in mongodb, as follows:
{"_ id": ObjectId ("5f38b83e0351908eedac60c9"), "StudentName": "hxc", "Created": ISODate ("2020-08-16T04:38:22.587Z")}
As can be seen from ISODate, this is Greenwich mean time, which is stored in the 0 time zone, so the question turns to how to automatically convert ISO time to Local time when obtaining data. If you look at the underlying source code, you will find that each type of entity in mongodb has a special XXXSerializer, as shown below:
Next, just take a good look at the Deserialize method in it. The code is simplified as follows:
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;}
As you can see, if the current this._kind= DateTimeKind.Local, convert the UTC time to Local time. If you have the experience of the last pit, you probably know that it should also be injected with features.
[BsonDateTimeOptions (Kind = DateTimeKind.Local)] public DateTime Created {get; set;}
If you don't believe me, I'll debug it and show you.
Let's take a look at how this._kind is assigned.
4: pit 3 Custom ObjectID
In the first pit, I don't know if you have seen a statement like this: ObjectId ("5f38b83e0351908eedac60c9"). At first glance, it looks like a GUID, but of course it's not. This is mongodb's own hexadecimal representation of a combination of number. Not to mention the performance, anyway, it doesn't look very comfortable. After all, everyone is used to using the primary key ID displayed by the int/long type.
Then the next question is: how can I change it to my custom number ID? Of course, as long as you implement the IIdGenerator interface, I'm going to use the snowflake algorithm to generate the primary key ID. The complete code is as follows:
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"); 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;}}
Then take a look at the json generated by mongodb:
On the use of mongodb on the three big pits whether to share here, I hope that the above content can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.