With mongodb and guids for the Id of documents wha

2019-01-14 12:19发布

问题:

I'm running version 2.06 of Mongodb and version (1.5) of the C# driver supplied by 10Gen.

Each of my entities has an Id property setup as such...

 [BsonId(IdGenerator = typeof(GuidGenerator))]
 public Guid Id { get; set; }

The Id field is stored as Binary - 3:UuidLegacy. Because of how it is stored when I call ToJson() on an entity it returns the following javascript object for the Id.

_id : Object
 $binary: "some values here"
 $type: "03"

This is obviously because the data is being stored as Binary = 3:UuidLegacy. This make sense.

I want to use the actual Guid in my Javascript code. How efficient would it be for MongoDB if I made my Id properties look like the following?

 [BsonId(IdGenerator = typeof(GuidGenerator)),MongoDB.Bson.Serialization.Attributes.BsonRepresentation(BsonType.String)]
public Guid Id { get; set; }

This makes mongodb store my Id as a string. But how efficient is this really? I'm guessing the Binary format for my Id is better, but I really need the Guid.

How can I go from Binary - 3:uuidLegacy to the Guid I need in my json?

I guess another thought would be could I just use the $binary value that is sent to me? I use the Id to perform lookups and such as part of my query strings.

Thanks,

回答1:

Working with GUIDs has a few pitfalls, mostly related to how to work with the binary representation in the mongo shell and also to historical accidents which resulted in different drivers storing GUIDs using different byte orders.

I used the following code to illustrate the issues:

var document = new BsonDocument { { "_id", Guid.NewGuid() }, { "x", 1 } };
collection.Drop();
collection.Insert(document);
Console.WriteLine("Inserted GUID: {0}", document["_id"].AsGuid);

which when I ran it output:

Inserted GUID: 2d25b9c6-6d30-4441-a360-47e7804c62be

when I display this in the mongo shell I get:

> var doc = db.test.findOne()
> doc
{ "_id" : BinData(3,"xrklLTBtQUSjYEfngExivg=="), "x" : 1 }
> doc._id.hex()
c6b9252d306d4144a36047e7804c62be
>

Notice that even when displayed as hex the byte order doesn't match the original GUID. That's the historical accident I was talking about. All the bytes are there, they're just in an unusual order thanks to Microsoft's implementation of Guid.ToByteArray().

To help you work with GUIDs in the mongo shell you could copy the following file of helper functions to the directory where mongo.exe is stored:

https://github.com/rstam/mongo-csharp-driver/blob/master/uuidhelpers.js

The file has some brief documentation comments at the top that you might find helpful. To make these functions available in the mongo shell you need to tell the mongo shell to read this file as it starts up. See the following sample session:

C:\mongodb\mongodb-win32-x86_64-2.0.6\bin>mongo --shell uuidhelpers.js
MongoDB shell version: 2.0.6
connecting to: test
type "help" for help
> var doc = db.test.findOne()
> doc
{ "_id" : BinData(3,"xrklLTBtQUSjYEfngExivg=="), "x" : 1 }
> doc._id.hex()
c6b9252d306d4144a36047e7804c62be
> doc._id.toCSUUID()
CSUUID("2d25b9c6-6d30-4441-a360-47e7804c62be")
>

You could also use another of the helper functions to query for the GUIDs:

> db.test.find({_id : CSUUID("2d25b9c6-6d30-4441-a360-47e7804c62be")})
{ "_id" : BinData(3,"xrklLTBtQUSjYEfngExivg=="), "x" : 1 }
>

As far as storing your GUIDs as strings, that's not an unheard of thing to do and it definitely makes viewing and querying the data in the mongo shell easier and avoids all the issues with different byte orders. The only disadvantage is that it uses more space (roughly double).



标签: c# mongodb