Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reduce cannot contain Average() methods in grouping

Tags:

c#

.net

ravendb

Just upgraded to v2 and this no longer works; I get a similar error if I try to use Count()

public class Deck_Ratings : AbstractIndexCreationTask<DeckRating, Deck_Ratings.ReduceResult>
{
    public class ReduceResult
    {
        public string DeckId { get; set; }
        public int Rating { get; set; }
    }

    public Deck_Ratings()
    {
        Map = deckRatings => deckRatings.Select(deckRating => new 
                             { 
                                 deckRating.DeckId, 
                                 deckRating.Rating 
                             });
        Reduce = reduceResults => reduceResults
                                      .GroupBy(reduceResult => reduceResult.DeckId)
                                      .Select(grouping => new 
                                              {
                                                  DeckId = grouping.Key, 
                                                  Rating = grouping.Average(reduceResult => reduceResult.Rating)
                                               });
    }
}
like image 709
Jon Canning Avatar asked Feb 17 '23 22:02

Jon Canning


1 Answers

Aggregates that can be influenced by the size of the reduce batch (such as Count and Average) are prohibited because they will yield the wrong results. You may have been able to use it under 1.0, but your averages were probably wrong unless you had so few items that they all got done in one reduce batch. To understand more about reduce batches, read Map / Reduce - A Visual Explanation

You must count items by summing a 1 for each item. You must average items by taking a sum of the values as a total, a sum of 1's as a count, and then dividing them.

public class Deck_Ratings : AbstractIndexCreationTask<DeckRating, Deck_Ratings.ReduceResult>
{
    public class ReduceResult
    {
        public string DeckId { get; set; }
        public int TotalRating { get; set; }
        public int CountRating { get; set; }
        public double AverageRating { get; set; }
    }

    public Deck_Ratings()
    {
        Map = deckRatings => deckRatings.Select(deckRating => new 
                             { 
                                 deckRating.DeckId,
                                 TotalRating = deckRating.Rating,
                                 CountRating = 1,
                                 AverageRating = 0
                             });
        Reduce = reduceResults => reduceResults
                                      .GroupBy(reduceResult => reduceResult.DeckId)
                                      .Select(grouping => new 
                                              {
                                                  DeckId = grouping.Key, 
                                                  TotalRating = grouping.Sum(reduceResult => reduceResult.TotalRating)
                                                  CountRating = grouping.Sum(reduceResult => reduceResult.CountRating)
                                               })
                                      .Select(x => new
                                               {
                                                  x.DeckId,
                                                  x.TotalRating,
                                                  x.CountRating,
                                                  AverageRating = x.TotalRating / x.CountRating
                                               });
    }
}
like image 85
Matt Johnson-Pint Avatar answered Feb 20 '23 11:02

Matt Johnson-Pint