使用 MongoDB C# driver 2.4 查询的 Include/Exclude 个字段

Include/Exclude fields in query with MongoDB C# driver 2.4

我们有一个collection包含文件的服务器。每个文件是这样的:

{ _id: "...", Prop1: "", Prop2: "", Prop3: "", LargeField: "", ... }

还有很多其他字段,但客户不需要。

我想将文档加载为 MyDoc class 其定义是:

public class MyDoc {
    public string Id { get; set; }
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
    public string Prop3 { get; set; }
    public string LargeField { get; set; }
}

我试过:

var client = new MongoClient(uri);
var database = client.GetDatabase("MyDatabase");
var collection = database.GetCollection<MyDocs>("MyDocs");
var allDocs = collection.Find().ToList();

然后它将加载每个文档的所有字段,因此我必须将 [BsonIgnoreExtraElements] 放在 MyDoc 上。这里的问题是文档很大,但我只需要有限的字段子集。是否可以让 driver 知道我只需要 class 中定义的字段?

如果不是,是否可以排除一些像LargeField这样的字段来缩小结果集?我试过:

var fieldsBuilder = Builders<MyDoc>.Projection;
var fields = fieldsBuilder.Exclude(d => d.LargeField);
var allDocs = collection.Find().Project(fields).ToList();

但现在 allDocs 变成了 BsonDocument 列表而不是 MyDoc 列表。如何用投影查询MyDoc

有人可以帮忙吗?它在传统 MongoDB driver 中相当简单,但我不知道如何在新 driver 中做到这一点。谢谢。

我遇到了类似的问题,我相信您需要指定泛型类型,出于某种原因,Project 会自动采用 BsonDocument。这应该将它从 BsonDocument 修复到您的 class.

变化:

var allDocs = collection.Find().Project(fields).ToList();

收件人:

var allDocs = collection.Find<MyDoc>().Project<MyDoc>(fields).ToList();

至于如何只包含某些字段,这可以像使用构建器(使用 Include)或使用 json 形式的字符串一样完成,例如:

var allDocs = collection.Find<MyDoc>().Project<MyDoc>("{Prop1: 1, Prop2: 1}").ToList();

我强烈建议您查看此人 post 的投影: https://www.codementor.io/pmbanugo/working-with-mongodb-in-net-part-3-skip-sort-limit-and-projections-oqfwncyka

来自这篇文章:

This brings us to another difference: with a projection definition, it implicitly converts the document type from Student to BsonDocument, so what we get back is a fluent object that, in result, will be a BsonDocument (even though what we're working with is the Student type). If we want to work with Student, we have to indicate that we still want to keep the type to Student.

更新的方式:

var fieldsBuilder = Builders<MyDoc>.Projection;
var fields = fieldsBuilder.Exclude(d => d.BigField1).Exclude(d => d.BigField2);

return Collection.Find(x => x.id.Equals(id)).Project<MyDoc>(fields).ToEnumerable();

吉娜

我们也可以使用 FindAsync。要在 FindSync 中使用投影,我们必须像这样传递 FindOptions 内容:它将 select countryName、ID 和 population。

FindAsync 以异步方式从数据库游标中逐一加载文档,当您拥有庞大的数据库时,这是一个不错的选择。

相关代码:


cursor = await collection.FindAsync(y => y.CountryID > 205,
                   new FindOptions<MyDoc, MyDoc>()
                   {
                       BatchSize = 20,
                       NoCursorTimeout = true,
                       AllowPartialResults = true,
                       Projection = "{'_id':1,'Name':1,'Population':1}"
                   }).ConfigureAwait(false);