我有这个简化的模型:
public class Parent
{
public ObjectId Id { get; set; }
}
public class Child
{
public ObjectId Id { get; set; }
public ObjectId ParentId { get; set; }
[BsonRepresentation(BsonType.String)]
public Gender Gender { get; set; }
}
我向父母询问了我故意省略的某些字段的过滤器。现在我有一个父ID集合。我想让所有Gender.Male
的孩子只为我通过第一个查询获得的父母并将其分组,以便我可以在Parent
和List<Child>
之间建立映射。
var parentIds = filteredParents.Select(p => p.Id).ToList();
var childrenFilter = Builders<Child>.Filter.In(c => c.ParentId, parentIds) &
Builders<Child>.Filter.Eq(c => c.Gender, Gender.Male);
var aggregation = children
.Aggregate()
.Match(childrenFilter)
.Group(c => c.ParentId, g => new KeyValuePair<string, List<Child>>(g.Key, new List<Child>(g)));
var groupCursor = await aggregation.ToCursorAsync();
然而这会抛出
System.NotSupportedException: Could not find a member match for constructor parameter collection on type List`1.
一些小问题
我假设我以这样的方式编写childrenFilter
,它将在服务器上执行,而客户端将不会收到Gender.Female
个孩子?如果那不是真的 - 做正确的方法是什么?如果我使用Linq.Expression
的重载 - 那么过滤器会在服务器上还是在客户端上执行?
孩子们是在服务器上还是在客户端上分组?我应该如何编写Group
以便在服务器上执行更高效的服务?
更新17.06
根据@ CraigWilson的建议,我尝试了g.ToList()
:
var aggregation = children
.Aggregate()
.Match(childrenFilter)
.Group(c => c.ParentId, g => new KeyValuePair<string, List<Child>>(g.Key, g.ToList()));
导致了一个不同的例外:
未处理的异常:System.AggregateException:发生了一个或多个错误。 --- System.InvalidCastException:无法将类型为'MongoDB.Driver.Linq.Expressions.SerializationExpression'的对象强制转换为'System.Linq.Expressions.MethodCallExpression'。