With the old driver I could specify the fields I wanted to return from a query as follows:
var cursor = Collection.Find(query).
SetFields(Fields<MealPlan>.Exclude (plan => plan.Meals));
How do I accomplish this with the 2.0 driver?
You need to use the Projection method on IFindFluent (which is what Find and Projection return):
var findFluent = Collection.Find(query).Projection(Fields<MealPlan>.Exclude (plan => plan.Meals))
Now, this would eventually generate a cursor of BsonDocuments since it doesn't know how the projection looks. You can call the generic Projection instead to add that type:
var findFluent = Collection.Find(query).Projection<MealPlan>(Fields<MealPlan>.Exclude (plan => plan.Meals))
In a more general sense (which is less relevant when using Exclude), you could also specify fields using a lambda expression:
var findFluent = Collection.Find(query).Projection(plan => plan.Meals)
Collection.Find(query).Projection<AbstractPlan>(Fields.Include("_id"))? No, it won't work as it tries to create an instance out of AbstractPlan. It can work if the base class isn't abstract but the instance would be of the base class and not the concrete type._id isn't returned by default from mongo)If you want SetFields back you can write your own extension method:
public static class MongoExtensions
{
public static IFindFluent<T, T> SetFields<T>(this IFindFluent<T, T> query, params string[] fields)
{
if ( fields == null || fields.Length == 0 )
{
return query;
}
var project = Builders<T>.Projection.IncludeAll<T>(fields);
return query.Project<T>(project);
}
public static ProjectionDefinition<T> IncludeAll<T>(this ProjectionDefinitionBuilder<T> projection,
params string[] fields)
{
ProjectionDefinition<T> project = null;
foreach (string columnName in fields)
{
if (project == null)
{
project = Builders<T>.Projection.Include(columnName);
}
else
{
project = project.Include(columnName);
}
}
return project;
}
}