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