[英]How can I find a document by GUID _id?
I use this code to retrieve some documents: 我使用此代码来检索一些文档:
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);
The results look like this: 结果如下所示:
{ "_id" : CSUUID("75c5634c-b64b-4484-81f5-5b213228e272"), ..., "created" : ISODate("2018-12-20T23:59:13.375Z") }
I'm having trouble retrieving this same document when trying to filter on _id. 在尝试过滤_id时,我在检索同一文档时遇到问题。 Here are the filters I've tried (using the same code as above) and have not been able to retrieve the document:
以下是我尝试过的过滤器(使用与上面相同的代码)并且无法检索文档:
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 } }";
Note, TGPFdUu2hESB9VshMijicg==
was retrieved by getting a base 64 encoded string from the guid like this: 注意,通过从guid获取base 64编码的字符串来检索
TGPFdUu2hESB9VshMijicg==
,如下所示:
Convert.ToBase64String((new Guid("75c5634c-b64b-4484-81f5-5b213228e272")).ToByteArray())
None of the queries throw any exceptions, but they return no documents. 没有任何查询抛出任何异常,但它们不返回任何文档。
Adding this before even creating MongoClient() resolved the issue for me: 在创建MongoClient()之前添加它解决了我的问题:
BsonDefaults.GuidRepresentation = GuidRepresentation.Standard;
It looks like on the C# side the MongoDB driver was interpreting it as a UUID with a binary subtype of 3. However, the documents saved in the collection had a binary subtype of 4. 看起来在C#端,MongoDB驱动程序将其解释为具有二进制子类型3的UUID。但是,保存在集合中的文档具有4的二进制子类型。
Also, after this change the document retrieved shows "UUID()" rather than "CSUUID()": 此外,在此更改后,检索到的文档显示“UUID()”而不是“CSUUID()”:
{ "_id" : UUID("75c5634c-b64b-4484-81f5-5b213228e272"), ..., "created" : ISODate("2018-12-20T23:59:13.375Z") }
After more time than I'd care to admit searching the web and testing many theories, the breakthrough came from skimming through this article: https://www.codeproject.com/Articles/987203/%2FArticles%2F987203%2FBest-Practices-for-GUID-data-in-MongoDB 经过一段时间,我不得不承认在网上搜索和测试许多理论,这一突破来自于浏览这篇文章: https : //www.codeproject.com/Articles/987203/%2FArticles%F987203%2FBest-Practices-换GUID数据功能于MongoDB中
Excerpt from that link: 摘自该链接:
MongoDB drivers usually store UUIDs as Binary fields with the legacy 0x03 subtype assigned by default.
MongoDB驱动程序通常将UUID存储为二进制字段,默认情况下分配旧的0x03子类型。 This configuration can be changed:
此配置可以更改:
C#:
C#:
You can override the driver's default settings and configure it to use the Binary 0x04 subtype by modifying the value of BsonDefaults.GuidRepresentation:
您可以通过修改BsonDefaults.GuidRepresentation的值来覆盖驱动程序的默认设置并将其配置为使用二进制0x04子类型:
BsonDefaults.GuidRepresentation = GuidRepresentation.Standard;
You can also modify GuidRepresentation at the server, database and collection level.
您还可以在服务器,数据库和集合级别修改GuidRepresentation。
EDIT: 编辑:
This is what I ended up using for the json filter: 这就是我最终用于json过滤器的内容:
var json = "{ \"_id\" : UUID(\"75c5634c-b64b-4484-81f5-5b213228e272\") }";
The MongoDb C# driver does a lot of work trying to keep you away of the Json (Bson) representation. MongoDb C#驱动程序做了很多工作,试图让你远离Json(Bson)表示。 To oversimplify, you have 3 ways of working with MongoDb with C#
为了过度简化,您有3种方式使用C#使用MongoDb
BsonDocument
class. BsonDocument
类。 And of course, a combination of the 3, which makes things much worse :-) 当然,3的组合,这使事情更糟:-)
So, in your case, here is how you would do the BsonDocument way (w/o any JSON): 所以,在你的情况下,这里是你如何做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"]);
And here is how you could do the typed-document way (w/o any JSON and w/o any BsonDocument): 以下是如何使用类型文档方式(没有任何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...
}
As you see, the last way is much simpler, but we can't always use it. 如您所见,最后一种方法更简单,但我们不能总是使用它。 BTW, it's sad that the driver doesn't allow to derive
MyDoc
from BsonDocument
, because we would truly have best of both worlds (it compiles but throws.... if MongoDb C# devs read this...) 顺便说一句,令人遗憾的是,驱动程序不允许从
BsonDocument
派生MyDoc
,因为我们真的会拥有两个世界中最好的(它编译但抛出......如果MongoDb C#devs读到这个......)
Now, concerning guids, you'll note the Console.WriteLine(foundDoc["_id"])
displays UuidLegacy:0x87fa981983de774b998868046e257b19
because MongoDb has a legacy history with guids. 现在,关于guids,你会注意到
Console.WriteLine(foundDoc["_id"])
显示UuidLegacy:0x87fa981983de774b998868046e257b19
因为MongoDb有guid的遗留历史记录。
As you found out, you can change BsonDefaults.GuidRepresentation
. 如您
BsonDefaults.GuidRepresentation
,您可以更改BsonDefaults.GuidRepresentation
。 By default it's CSharpLegacy
. 默认情况下,它是
CSharpLegacy
。
Here is a list of prefixes used when guids are displayed as strings throughout code (client or server): 以下是guids在整个代码(客户端或服务器)中显示为字符串时使用的前缀列表:
The 2 and 3 approaches also shield you from these "internal" MongoDb issues. 2和3方法也可以保护您免受这些“内部”MongoDb问题的影响。 If you use these, you don't have to change
BsonDefaults.GuidRepresentation
. 如果您使用这些, 则无需更改
BsonDefaults.GuidRepresentation
。
So my advise is try to stay away from Json when programming MongoDb with C#. 因此,我建议在使用C#编写MongoDb时远离Json。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.