如何通过 C# 驱动程序查询 MongoDB 以获取嵌入式文档
本文关键字:获取 嵌入式 文档 MongoDB 查询 何通过 驱动程序 | 更新日期: 2023-09-27 17:56:20
我想知道如何通过官方 C# 驱动程序版本 1.7 查询 MongoDB 集合中的嵌入式文档(在数组中)?通过查询嵌入文档,我的意思是我只想检索嵌入的文档,而不是包含它的文档,即投影。
我正在查询带有嵌入式文档的数据模型类型示例:
// Library, contained in db.Libraries
{
_id: 1,
Categories: [{_id: 2, Name: "Classics", Books: [{_id: 3, Name: The Count of Monte Cristo}]}]
}
这里的问题是如何在库集合中查询具有 _id
1 的对象和具有 _id
3 的书籍之一,并仅返回 Book。它可行吗?据我所知,可以通过MongoDB shell中的投影来做到这一点。
我的示例查询是查询数据库。包含_id
3 的书籍的库包含在包含_id
1 的库中。返回的书将是以下子文档:
{_id: 3, Name: The Count of Monte Cristo}]}
我已经看过如何使用MongoDB的官方C#驱动程序检索嵌入式文档的问题?,但我无法使接受的答案对我有用。
编辑:
我现在可以看到,如何使用MongoDB的官方C#驱动程序检索嵌入式文档的公认答案?我没有看到它遍历每个找到的文档,相当于这样:
var libraryCollection = new MongoCollection<Library>();
var refBook = new Book { Id = ObjectId.GenerateNewId().ToString(), Name = "The Count of Monte Cristo" };
libraryCollection.Insert(new Library { Id = ObjectId.GenerateNewId().ToString(), Categories = new[] { new Category { Books = new[] { refBook } } } });
MongoCursor<Library> libraries = libraryCollection.Find(new QueryDocument(
new Dictionary<string, object>
{
{"_id", new ObjectId()},
}
));
Book book;
foreach (var library in libraries)
{
book = library.Categories.SelectMany(c => c.Books).FirstOrDefault(b => b.Id == refBook.Id);
}
但是,此解决方案没有实际意义,因为它检索整个图书馆文档,而不仅仅是嵌入的书籍文档。我真的不得不只反序列化嵌入式书籍,也就是投影。
要执行投影,其中生成的文档不仅被过滤,而且被重塑,您需要使用 Aggregate
而不是像这样Find
方法之一:
var result = collection.Aggregate(
// Only include the document where _id = 1
new BsonDocument {{"$match", new BsonDocument {{"_id", 1}}}},
// 'Unwind' the Categories array by duplicating the docs, one per element.
new BsonDocument {{"$unwind", "$Categories"}},
// Now do the same for the Books array inside each Categories element.
new BsonDocument {{"$unwind", "$Categories.Books"}},
// Only include the resulting docs with a Book _id of 3
new BsonDocument {{"$match", new BsonDocument {{"Categories.Books._id", 3}}}},
// Reshape the document to bring the book attributes out to the top level
new BsonDocument {{"$project", new BsonDocument {
{"_id", "$Categories.Books._id"},
{"Name", "$Categories.Books.Name"}
}}}
);
result.Response.toJson()
:
{"result": [{ "_id": 3.0, "Name": "The Count of Monte Cristo" }], "ok": 1.0 }