在MongoDB驱动程序

时间:2018-01-18 14:59:33

标签: c# mongodb linq

我希望根据某些键获得不同的对象。以下是我在mongodb中的表现:

db.collection.aggregate(
   [
     { $match: filter },
     {
        $group:
        {
           _id: distinctField,
           value: { $first: "$$ROOT" } // taking any of group because we don't care
        }
     },
     { $replaceRoot : { newRoot: "$value" }}
   ]
)

它按预期工作。但后来我试着在C#中做到这一点:

public static IAggregateFluent<T> WhereDistinct<T, TKey>(this IMongoCollection<T> collection, FilterDefinition<T> filter, Expression<Func<T, TKey>> distinctField) => 
    collection.Aggregate()
            .Match(filter)
            .Group(distinctField, items => new { Value = items.FirstOrDefault() }) // taking any of group because we don't care
            .ReplaceRoot(arg => arg.Value);

我得到一个例外:

  

其他信息:System.Linq.Enumerable类型的FirstOrDefault   表达式树{document}中不支持.OrderByDescending(c   =&GT; c.Version).FirstOrDefault()。

是否可以在不创建令人讨厌的BsonDocument查询的情况下执行此操作?我知道我可以手动编写整个内容,但我想使用一些基于linq的方法。

1 个答案:

答案 0 :(得分:0)

感谢@chridam,我知道没有clean way来执行此操作。

但是,这种扩展方法可能会有所帮助。它完全是我在JS中编写的,但为C#提供了一些不错的API

public static IAggregateFluent<T> WhereDistinct<T, TKey>(this IMongoCollection<T> collection,
    FilterDefinition<T> filter, Expression<Func<T, TKey>> distinctField) =>
    collection.Aggregate()
        .Match(filter)
        .Group(new BsonDocument
        {
            {"_id", $"${((MemberExpression) distinctField.Body).Member.Name}"},
            {"doc", new BsonDocument {{"$first", "$$ROOT"}}} // taking any of group because we don't care
        })
        .ReplaceRoot<T>("$doc");