首页 > 解决方案 > 如何使用 C# 在 MongoDb 的 Find(filter, options) 中设置投影?

问题描述

我收到以下语法的编译错误。

var index = ...;
var projection = Builders<Thing>.Projection
  .Include(a => a.Name)
  .Include(a => a.Stuff[index]);

var options = new FindOptions<Thing, Thing> { Projection = projection };
var filter = Builders<Thing>.Filter.Where(a => a.Name == name);

var output = await _dbContext.Things.Find(filter, options)
  .SingleOrDefaultAsync(token);

return output;

计算机对我的选项不满意,要求它们是非通用的。但是,如果我使用FindOptions而不是FindOptions<A,B>,则没有Projection要设置的属性。因为我确实需要我的投影,所以我一定会使用通用版本。

我还注意到我可以使用FindAsync(...), 而不是Find(...), 这似乎接受了通用版本。遗憾的是,这不是一个选项,因为该方法的签名是返回Task<Thing>,我得到Task<IAsyncCursor<Thing>>. 我被困在如何去游标,获取集合中的单个元素(唯一的命名保证)返回正确类型的任务。(如果我去ToList(),异步被杀死。)

那里没有很多例子。

我有一个工作的 mongo 脚本,但它正在将它翻译成 C#,这是一个很大的障碍。

db.getCollection('things').find(
  { name: "blobbo" },
  { "stuff.shazoo": 1, name: 1 }
)

标签: c#mongodbprojection

解决方案


假设您的模型如下所示:

public class Thing
{
    public string Name { get; set; }
    public Stuff[] Stuff { get; set; }
}

public class Stuff
{
    public string Shazoo { get; set; }
    public string Foofoo { get; set; }
}

您可以通过聚合获得所需的结果,如下所示:

var projection = Builders<Thing>.Projection.Expression(
    t => new Thing
    {
        ID = t.ID,
        Name = t.Name,
        Stuff = t.Stuff.Select(s => new Stuff { Shazoo = s.Shazoo }).ToArray()
    });

var things = await collection
    .Aggregate()
    .Match(filter)
    .Project(projection)
    .ToListAsync();

推荐阅读