I have a domain class like this.
public class Thing
{
public Guid Id { get; set; }
public string Name { get; set; }
public Dictionary<string, string> Stuff { get; set; }
}
I'm retrieving it from my DB using the following.
return await _db.Things
.Find(x => x.Name == name)
.SingleOrDefaultAsync(token);
As I noticed, there might be huge chunks of unnecessary data so I used a projection like this.
ProjectionDefinition<Thing> projection = Builders<Thing>
.Projection
.Include(a => a.Id)
.Include(a => a.Name);
BsonDocument projected = await _dbContext.Things
.Find(x => x.Name == name)
.Project(projection)
.SingleOrDefaultAsync(token);
This works but, naturally, cuts of all the dictionary contents. I'd like to alter the definition of projection to include the field but perform a filtration of the constituting elements. Suppose I'd only want to bring in the keys of said dictionary that start with duck. An attempt might be something like this.
ProjectionDefinition<Thing> projection = Builders<Thing>
.Projection
.Include(a => a.Id)
.Include(a => a.Name)
.Include(a => a.Stuff.Where(b => b.Key.StartsWith("duck")));
That resulted in exception as follows.
System.NotSupportedException: The expression tree is not supported: {document}{configuration}
Given my ignorance with MongoDb, I have no idea if I should add something, remove something or forget the idea all together. I also tried to work with the original type to be able to filter the stuff that way but the only solution I've got was post-fetch, basically trumming the retrieved data. I'd like to lower the payload from the DB to my service.
Thing projected = await _dbContext.Things
.Find(x => x.Name == name)
.Project<Thing>(projection)
.SingleOrDefaultAsync(token);
Is it doable at all and if so, how (or at least what to google for)?
Proof of effort: code examples, general operations, tutorials, wrong answers etc. It might be out there somewhere but I failed to find it (or recognize if found).
Finally, I landed into the following - God forgive me for I know not what I'm doing. Is this at all in the right direction or is a gang of crazy donkeys going to bite me in the lower back for this?!
ProjectionDefinition<Thing, Thing> wtf = Builders<Thing>.Projection
.Expression(a => new Thing
{
Id = a.Id,
Name = a.Name,
Stuff = a.Stuff
.Where(b => b.Key == scope)
.ToDictionary(b => scope, b => b.Value)
});