С mongodb и guids для Id документов, что является эффективным способом хранения Гидов, чтобы легко получить фактический Guid?

Я запускаю версию 2.06 Mongodb и версию (1.5) драйвера С#, поставляемую 10Gen.

Каждый из моих объектов имеет настройку свойства Id как таковой...

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

Поле Id хранится как двоичное - 3: UuidLegacy. Из-за того, как он хранится, когда я вызываю ToJson() в сущности, он возвращает следующий объект javascript для Id.

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

Это, очевидно, потому, что данные хранятся как Binary = 3: UuidLegacy. Это имеет смысл.

Я хочу использовать фактическое руководство в своем JavaScript-коде. Насколько эффективно для MongoDB, если бы мои свойства Id выглядели следующим образом?

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

Это делает mongodb хранить мой идентификатор в виде строки. Но насколько это эффективно? Я предполагаю, что двоичный формат для моего идентификатора лучше, но мне действительно нужен Guid.

Как я могу перейти от Binary - 3: uuidLegacy к руководству, которое мне нужно в моем json?

Думаю, еще одна мысль: я могу просто использовать $двоичное значение, которое отправлено мне? Я использую Id для выполнения поиска и, например, часть строк запроса.

Спасибо,

Ответы

Ответ 1

Работа с GUID имеет несколько подводных камней, в основном связанных с работой с бинарным представлением в оболочке mongo, а также с историческими авариями, в результате которых разные драйверы сохраняют GUID с использованием разных порядков байтов.

Я использовал следующий код, чтобы проиллюстрировать проблемы:

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

который, когда я запускал его вывод:

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

когда я показываю это в оболочке mongo, я получаю:

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

Обратите внимание, что даже при отображении в виде шестнадцатеричного байта порядок байтов не соответствует исходному GUID. Это историческая катастрофа, о которой я говорил. Все байты есть, они просто необычны, благодаря внедрению Microsoft Guid.ToByteArray().

Чтобы помочь вам работать с GUID в оболочке mongo, вы можете скопировать следующий файл вспомогательных функций в каталог, где хранится mongo.exe:

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

В файле есть краткие комментарии к документации наверху, которые могут оказаться полезными. Чтобы эти функции были доступны в оболочке mongo, вам нужно сказать оболочке mongo, чтобы прочитать этот файл по мере его запуска. См. Следующий пример:

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")
>

Вы также можете использовать другую вспомогательную функцию для запроса идентификаторов GUID:

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

Что касается хранения ваших GUID как строк, это не неслыханная вещь, и это определенно упрощает просмотр и запрос данных в оболочке mongo и устраняет все проблемы с разными байтовыми заказами. Единственным недостатком является то, что он использует больше места (примерно вдвое).