23

Mongodb のバージョン 2.06 と、10Gen が提供する C# ドライバーのバージョン (1.5) を実行しています。

私のエンティティのそれぞれには、そのような Id プロパティが設定されています...

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

Id フィールドは Binary - 3:UuidLegacy として保存されます。エンティティで ToJson() を呼び出すと、それがどのように格納されるかにより、Id に対して次の JavaScript オブジェクトが返されます。

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

これは明らかに、データが Binary = 3:UuidLegacy として格納されているためです。これは理にかなっています。

Javascript コードで実際の G​​uid を使用したいと考えています。Id プロパティを次のようにすると、MongoDB はどのくらい効率的になりますか?

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

これにより、mongodb は ID を文字列として保存します。しかし、これは実際にどのくらい効率的ですか?Id のバイナリ形式の方が優れていると思いますが、実際には Guid が必要です。

Binary - 3:uuidLegacy から JSON で必要な Guid に移動するにはどうすればよいですか?

別の考えは、私に送信された $binary 値を使用することでしょうか? Id を使用してルックアップを実行し、クエリ文字列の一部として使用します。

ありがとう、

4

1 に答える 1

36

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
>

16 進数として表示されている場合でも、バイト オーダーが元の GUID と一致しないことに注意してください。それが私が話していた歴史的な事故です。Microsoft の Guid.ToByteArray() の実装により、すべてのバイトが異常な順序になっています。

mongo シェルで GUID を操作しやすくするために、次のヘルパー関数のファイルを 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 シェルでのデータの表示とクエリが確実に簡単になり、さまざまなバイト オーダーに関するすべての問題が回避されます。唯一の欠点は、より多くのスペースを使用することです (約 2 倍)。

于 2012-07-06T14:34:55.113 に答える