【问题标题】:Include/Exclude fields in query with MongoDB C# driver 2.4使用 MongoDB C# 驱动程序 2.4 在查询中包含/排除字段
【发布时间】:2017-03-20 15:47:05
【问题描述】:

我们在服务器中有一个包含文档的集合。每个文档都是这样的:

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

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

我想将文档加载为MyDoc 类,其定义为:

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 上。这里的问题是文档很大,但我只需要有限的字段子集。是否可以让司机知道我只需要类中定义的字段?

如果没有,是否可以排除一些像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 驱动程序中它相当简单,但我不知道如何在新驱动程序中做到这一点。谢谢。

【问题讨论】:

    标签: mongodb-.net-driver


    【解决方案1】:

    我有一个类似的问题,我相信你需要指定泛型类型,由于某种原因 Project 自动假定 BsonDocument。这应该将它从 BsonDocument 修复到您的班级。

    变化:

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

    收件人:

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

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

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

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

    来自这篇文章:

    这给我们带来了另一个不同之处:使用投影定义,它将文档类型从 Student 隐式转换为 BsonDocument,因此我们得到的是一个流畅的对象,结果将是一个 BsonDocument(即使我们'重新工作的是学生类型)。如果我们想使用 Student,我们必须表明我们仍然希望将类型保留为 Student。

    【讨论】:

      【解决方案2】:

      一种更新的方式:

      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();
      

      吉娜

      【讨论】:

        【解决方案3】:

        我们也可以使用FindAsync。要在FindSync 中使用投影,我们必须像这样传递FindOptions:它将选择国家名称、ID 和人口。

        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);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-03-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-04-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多