Projection of mongodb subdocument using C# .NET driver 2.0

Lynchy picture Lynchy · Apr 18, 2015 · Viewed 29k times · Source

I have the following structure:

public class Category
{
    [BsonElement("name")]
    public string CategoryName { get; set; }

    [BsonDateTimeOptions]
    [BsonElement("dateCreated")]
    public DateTime DateStamp { get; set; }

    [BsonElement("tasks")]        
    public List<TaskTracker.Task> Task { get; set; }
}

public class Task
{
    [BsonElement("name")]
    public string TaskName { get; set; }

    [BsonElement("body")]
    public string TaskBody { get; set; }
}

I am trying to query a Category to get all the TaskName values and then return them to a list to be displayed in a list box.

I have tried using this query:

var getTasks = Categories.Find<Category>(x => x.CategoryName == catName)
                         .Project(Builders<Category>.Projection
                                                    .Include("tasks.name")
                                                    .Exclude("_id"))
                         .ToListAsync()
                         .Result;   

But what get returned is: {"tasks": [{"name: "test"}]}.

Is there anyway to just return the string value?

Answer

Craig Wilson picture Craig Wilson · Apr 18, 2015

As Avish said, you have to use the aggregation API to get the resulting document to look like you are wanting. However, the driver can make some of that disappear for you if you use the expression tree API for project as you have done for Find. For instance, I believe the following should work for you:

var taskNames = await Categores.Find(x => x.CategoryName == catName)
    .Project(x => x.Tasks.Select(y => y.Name))
    .ToListAsync();

This should just bring back an enumerable of strings (tasks.name) for each category. The driver will be inspecting this projection and only pull back the tasks.name field.