C# Driver- LINQ - Aggragate - Содержится в Int[]
Mongo Driver Version: 2.2.4.26
У меня есть следующий запрос, который выполняет некоторые агрегации. Если я удалю предикат Contains из моего предложения Where, запрос будет выполнен успешно.
Я хотел бы уменьшить и выполнить агрегацию на сервере перед реализацией данных в память клиента. Проблема, с которой я сталкиваюсь, заключается в том, что при использовании Contains в предложении Where я получаю следующее исключение:
$ 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();
1 ответ
Так как драйвер не любит 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);
}
}
Список целых = новый список () {1,2,3};
var predicate = PredicateBuilder.False<Forecast>();
foreach (var i in ints)
{
predicate = predicate.Or(x => x.MarkdownGroupId == i);
}
varcastProductDay = _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();