使用RavenDB计算简单平均值的正确方法是什么?
我的对象:
class Song
{
public int CommunityRank { get; set; }
}
我的第一个天真的想法是,“我只会使用.Sum!”,但我收到一个运行时错误,说Raven因性能原因不这样做,这是有道理的。
接下来的想法是,“我会制作一个小地图/缩小指数来计算它!”所以我想出了这个:
public Songs_CommunityRankIndex()
{
Map = songs => from song in songs
select new
{
Id = song.Id, // # Hack? I only use this for grouping in the reduce.
SongCount = 1,
RankSum = song.CommunityRank
};
Reduce = results => from result in results
group result by result.Id into g
select new
{
Id = default(string),
SongCount = g.Sum(s => s.SongCount),
RankSum = g.Sum(s => s.RankSum)
};
}
...
// Now to calculate the average:
var communityRankStats = session
.Query<Song, Songs_CommunityRankIndex>()
.As<Songs_CommunityRankIndex.Results>()
.FirstOrDefault();
if (communityRankStats != null)
{
var averageSongRank = (double)communityRankStats.RankSum / communityRankStats.SongCount;
}
我觉得这很有效,但感觉很乱,因为实际上没有什么可以分组的,所以我只是按照歌曲ID分组。
有更好的方法吗?
答案 0 :(得分:3)
如果要为单个结果对所有项目进行分组,则只需按常量值进行分组,例如零。
虽然在客户端进行操作没有任何问题,但通常可以方便地计算索引本身内部的平均值。只要总和是通过map / reduce完成的,那么如果划分客户端或服务器端并不重要。
public class Songs_CommunityRankIndex : AbstractIndexCreationTask<Song, Songs_CommunityRankIndex.Results>
{
public class Results
{
public long SongCount { get; set; }
public long RankSum { get; set; }
public double RankAverage { get; set; }
}
public Songs_CommunityRankIndex()
{
Map = songs => from song in songs
select new
{
SongCount = 1,
RankSum = song.CommunityRank,
RankAverage = 0
};
Reduce = results => from result in results
group result by 0
into g
let songCount = g.Sum(s => s.SongCount)
let rankSum = g.Sum(s => s.RankSum)
select new
{
SongCount = songCount,
RankSum = rankSum,
RankAverage = rankSum / songCount
};
}
}