2017-08-14 47 views
1

Mongo Driver版本:2.2.4.26C#驅動程序 - LINQ - Aggragate - 包含在Int []

我有以下查詢,執行一些聚合。如果我從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

這可能是驅動程序中的錯誤。如果將表達式轉換爲'Where(x => x.MarkdownGroupId == 1 || x.MarkdownGroupId == 2 || x.MarkdownGroupId == 3)',它會起作用嗎? – dasblinkenlight

+0

是的。這工作 轉換爲Where(x => x.MarkdownGroupId == 1 || x.MarkdownGroupId == 2 || x.MarkdownGroupId == 3) –

+0

您在列表中有多少個ID?也許你可以動態創建一個OR列表來解決這個問題。 – dasblinkenlight

回答

2

由於司機不喜歡載有()或任何()。我使用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(); 
相關問題