Konrad Viltersten
Konrad Viltersten

Reputation: 39190

How to set projection in Find(filter, options) in MongoDb using C#?

I get compile errors with the following syntax.

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;

The computer is unhappy with my options, requiring them to be non-generic. However, if I use FindOptions instead of FindOptions<A,B>, there's no property Projection to be set. Since I do need my projection, I'm bound to use the generic version.

I also noticed that I could use FindAsync(...), instead of Find(...), which seems to accept the generic version. Regrettably, it's not an option because the signature of the method is to return Task<Thing> and I'm getting Task<IAsyncCursor<Thing>>. I get stuck on how to de-cursorify, obtain the single element in the set (unique naming guarantees that) return the task of correct type. (If I go ToList(), the asynchronicity is killed.)

There's no many examples out there.

I have a working mongo script for that but it's translating it into C# that the big obstacle.

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

Upvotes: 1

Views: 1319

Answers (1)

Dĵ ΝιΓΞΗΛψΚ
Dĵ ΝιΓΞΗΛψΚ

Reputation: 5679

assuming your models look like this:

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

you can get the desired result via aggregation like so:

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

Upvotes: 2

Related Questions