Mongo驱动程序版本:2.2.4.26
我有以下查询执行一些聚合。如果我从Where子句中删除Contains谓词,查询将成功执行。
我希望在将数据实现到客户端内存之前减少并执行服务器上的聚合。我遇到的问题是当我在Where子句中使用Contains时,我得到以下异常:
$ project或$ group不支持Sum({document} {ForecastQuantity})。
如果可能的话,我宁愿继续使用linq实现而不是本机:
public class Forecast
{
public int MarkdownGroupId { get; set; }
public List<ForecastData> ForecastArray { get; set; }
...
}
public class ForecastData
{
public int MarkdownNumber { get; set; }
public double ForecastQuantity { get; set; }
...
}
public class Flat
{
public int MarkdownGroupId { get; set; }
public int MarkdownNumber { get; set; }
public double SalesQuantity { get; set; }
...
}
public class FlatProjection
{
public int MarkdownGroupId { get; set; }
public int MarkdownNumber { get; set; }
public double SalesQuantity { get; set; }
...
}
int[] groupIds = new int[]{ 1,2,3 };
var forecastProductDay = _mdb.GetCollection<Forecast>(collectionName);
var forecastProductProjections = forecastProductDay
.AsQueryable()
.Where(x => groupIds.Contains(x.MarkdownGroupId))
.SelectMany(x => x.ForecastArray, (x, fa) => new Flat
{
MarkdownGroupId = x.MarkdownGroupId,
MarkdownNumber = fa.MarkdownNumber,
ForecastQuantity = fa.ForecastQuantity,
...
})
.GroupBy(key => new {key.MarkdownGroupId, key.MarkdownNumber})
.Select(g => new FlatProjection
{
MarkdownGroupId = g.Key.MarkdownGroupId,
MarkdownNumber = g.Key.MarkdownNumber,
SalesQuantity = g.Sum(y => y.ForecastQuantity),
...
})
.OrderBy(x => x.MarkdownGroupId)
.ThenBy(x => x.MarkdownNumber)
.ToList();
答案 0 :(得分:2)
由于驱动程序不喜欢Contains()或Any()。我使用PredicateBuilder动态构建了表达式。
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
}
}
List ints = new List(){1,2,3};
var predicate = PredicateBuilder.False<Forecast>();
foreach (var i in ints)
{
predicate = predicate.Or(x => x.MarkdownGroupId == i);
}
var forecastProductDay = _mdb.GetCollection(collectionName);
var forecastProductProjections = forecastProductDay
.AsQueryable()
.Where(predicate.Compile())
.SelectMany(x => x.ForecastArray, (x, fa) => new Flat
{
MarkdownGroupId = x.MarkdownGroupId,
MarkdownNumber = fa.MarkdownNumber,
ForecastQuantity = fa.ForecastQuantity,
...
})
.GroupBy(key => new {key.MarkdownGroupId, key.MarkdownNumber})
.Select(g => new FlatProjection
{
MarkdownGroupId = g.Key.MarkdownGroupId,
MarkdownNumber = g.Key.MarkdownNumber,
SalesQuantity = g.Sum(y => y.ForecastQuantity),
...
})
.OrderBy(x => x.MarkdownGroupId)
.ThenBy(x => x.MarkdownNumber)
.ToList();