如何通过GUID _id查找文档?

时间:2018-12-26 12:32:37

标签: c# mongodb

我使用以下代码检索一些文档:

var client = new MongoClient(connectionString);
var database = client.GetDatabase(databaseName);
var collection = database.GetCollection<BsonDocument>(collectionName);

var json = "{created: {$gte: ISODate(\"2018-12-20T00:00:00.000Z\"), $lt: 
ISODate(\"2018-12-21T00:00:00.000Z\")}}";
BsonDocument query = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>(json);
var documents = collection.Find(query).Limit(10);

结果如下:

{ "_id" : CSUUID("75c5634c-b64b-4484-81f5-5b213228e272"), ..., "created" : ISODate("2018-12-20T23:59:13.375Z") }

尝试过滤_id时,我在检索同一文档时遇到麻烦。 这是我尝试过的过滤器(使用与上述相同的代码),但无法检索该文档:

var json = "{ \"_id\" : \"75c5634c-b64b-4484-81f5-5b213228e272\" }";
var json = "{ \"_id\" : CSUUID(\"75c5634c-b64b-4484-81f5-5b213228e272\") }";
var json = "{ \"_id\" : new BinData(4, \"TGPFdUu2hESB9VshMijicg==\") }";
var json = "{ \"_id\" : BinData(4, \"TGPFdUu2hESB9VshMijicg==\") }";
var json = "{ \"_id\" : new BinData(3, \"TGPFdUu2hESB9VshMijicg==\") }";
var json = "{ \"_id\" : BinData(3, \"TGPFdUu2hESB9VshMijicg==\") }";
var json = "{ \"_id\" : { $eq: \"TGPFdUu2hESB9VshMijicg==\" } }";
var json = "{ \"_id\" : { $binary: \"TGPFdUu2hESB9VshMijicg==\", $type: 4 } }";
var json = "{ \"_id\" : { $binary: \"TGPFdUu2hESB9VshMijicg==\", $type: 3 } }";

注意,TGPFdUu2hESB9VshMijicg==是通过从GUID获取以64为基数的字符串来检索的,如下所示:

Convert.ToBase64String((new Guid("75c5634c-b64b-4484-81f5-5b213228e272")).ToByteArray())

所有查询都不会引发任何异常,但是它们不返回任何文档。

2 个答案:

答案 0 :(得分:4)

甚至在创建MongoClient()之前添加此命令即可为我解决问题:

BsonDefaults.GuidRepresentation = GuidRepresentation.Standard;

在C#端,MongoDB驱动程序似乎将其解释为二进制子类型为3的UUID。但是,保存在集合中的文档的二进制子类型为4。

此外,在此更改之后,检索到的文档将显示“ UUID()”而不是“ CSUUID()”:

{ "_id" : UUID("75c5634c-b64b-4484-81f5-5b213228e272"), ..., "created" : ISODate("2018-12-20T23:59:13.375Z") }

经过比我更愿意承认的时间搜索网络并测试了许多理论之后,突破来自于浏览本文:https://www.codeproject.com/Articles/987203/%2FArticles%2F987203%2FBest-Practices-for-GUID-data-in-MongoDB

该链接的摘录:

  

MongoDB驱动程序通常将UUID与旧版存储为Binary字段   默认分配的0x03子类型。可以更改此配置:

     

C#:

     

您可以覆盖驱动程序的默认设置并将其配置为使用   二进制0x04子类型,方法是修改   BsonDefaults.GuidRepresentation:

BsonDefaults.GuidRepresentation = GuidRepresentation.Standard; 
     

您还可以在以下位置修改GuidRepresentation   服务器,数据库和收集级别。

编辑:

这是我最终用于json过滤器的内容:

var json = "{ \"_id\" : UUID(\"75c5634c-b64b-4484-81f5-5b213228e272\") }";

答案 1 :(得分:3)

MongoDb C#驱动程序做了很多工作,试图使您远离Json(Bson)表示形式。 为了简化起见,您有3种使用C#来使用MongoDb的方法。

  • 使用原始Json(非常“服务器端”编程)。
  • 使用瑞士军刀BsonDocument类。
  • 使用类型化的C#类。

当然,这三个因素的结合会使情况变得更糟:-)

因此,在您的情况下,这是您将如何使用BsonDocument方式(不使用任何JSON):

var client = new MongoClient(myConnectionString);
var db = client.GetDatabase("myDb");
var guid = Guid.NewGuid();

// create an untyped document
var doc = new BsonDocument { { "_id", guid } };
var coll = db.GetCollection<BsonDocument>("myColl");
coll.InsertOne(doc);

// Builders<T> is central to help you build all sorts of mongodb JSON jargon (filters, sort, projections, etc.)
// instead of building it by yourself
var filter = Builders<BsonDocument>.Filter.Eq(new StringFieldDefinition<BsonDocument, Guid>("_id"), guid);
var foundDoc = coll.Find(filter).FirstOrDefault();
Console.WriteLine(foundDoc["_id"]);

这是您可以执行键入文档方式(不带任何JSON和不带任何BsonDocument)的方法:

var client = new MongoClient(myConnectionString);
var db = client.GetDatabase("myDb");
var guid = Guid.NewGuid();

// create a class
var doc = new MyDoc { Id = guid };
var coll = db.GetCollection<MyDoc>("myColl");
coll.InsertOne(doc);

// we use a type that correspond to our busines layer/logic
// that's the easier way because you can use Linq syntax so we're far from JSON and document issues
// plus it's super readable in C#
var foundDoc = coll.Find(d => d.Id == guid).FirstOrDefault();
Console.WriteLine(foundDoc.Id);
...

// the typed-document (class)
class MyDoc
{
    [BsonId]
    public Guid Id { get; set; }

    ... other properties...
}

如您所见,最后一种方法要简单得多,但是我们不能总是使用它。 顺便说一句,令人遗憾的是,驱动程序不允许从MyDoc派生BsonDocument,因为我们确实拥有两全其美的优势(编译但抛出……。如果MongoDb C#开发人员阅读了此内容。 ..)

现在,关于GUID,您会注意到Console.WriteLine(foundDoc["_id"])显示UuidLegacy:0x87fa981983de774b998868046e257b19,因为MongoDb具有GUID的历史记录。

您发现,可以更改BsonDefaults.GuidRepresentation。默认情况下为CSharpLegacy

以下是在整个代码(客户端或服务器)中将guid显示为字符串时使用的前缀列表:

  • UUID:标准版本(不是旧版)
  • LUUID:旧版(仅在服务器上可见)
  • CSUUID:C#旧版(仅在客户端上可见)
  • JUUID:Java旧版(仅在客户端上可见)
  • PYUUID:Python旧版(仅在客户端上可见)

2和3方法也使您免受这些“内部” MongoDb问题的困扰。如果使用这些,则不必更改BsonDefaults.GuidRepresentation

因此,我的建议是在使用C#编程MongoDb时,尽量远离Json。