2012-01-27 51 views
1

只是在想,我应该怎么我的文档模型,这种情况下你的意见。大多重映射+减少或进行非标准化计数字段

目前我似乎有一个复杂的MultiMap索引,它从几个其他文档集合中提取计数器/统计信息,在我的开发机器上,它返回了80ms以下的测试数据的一小部分(我很满意)。

什么是性能将是这个时候我去生产服务器上一样,平均每个组合将每周收到约500次,每周200个下载和顶,收藏和评论了一把。我将每页显示20-25个混音。

你保留这个设计,也将是更好的非规范化我的柜台,并将其存储在音频文件,使用索引会少了很多工作,只要它会执行好不好?

public class AudioWithCounters : AbstractMultiMapIndexCreationTask<AudioWithCounters.AudioViewModel> 
    { 
     public class AudioViewModel 
     { 
      public string Id { get; set; } 
      public string ArtistName { get; set; } 
      public string Name { get; set; } 
      public int TotalComments { get; set; } 
      public int TotalDownloads { get; set; } 
      public int TotalPlays { get; set; } 
      public int TotalLikes { get; set; } 
      public int TotalFavourites { get; set; } 
      public int WeeksComments { get; set; } 
      public int WeeksDownloads { get; set; } 
      public int WeeksPlays { get; set; } 
      public int WeeksLikes { get; set; } 
      public int WeeksFavourites { get; set; } 
     } 

     public AudioWithCounters() 
     { 
      AddMap<Audio>(audios => from audio in audios 
            select new 
            { 
             Id = audio.Id, 
             ArtistName = audio.ArtistName, 
             Name = audio.Name, 
             TotalDownloads = 0, 
             TotalComments = audio.CommentsCount, 
             TotalPlays = 0, 
             TotalLikes = 0, 
             TotalFavourites = 0, 
             WeeksDownloads = 0, 
             WeeksPlays = 0, 
             WeeksComments = 0, 
             WeeksLikes = 0, 
             WeeksFavourites = 0 
            }); 

      AddMap<AudioComments>(comments => from audioComment in comments 
               from comment in audioComment.Comments 
               where comment.CreatedAt >= DateTimeOffset.Now.AddDays(-7) 
            select new 
            { 
             Id = audioComment.Audio.Id, 
             ArtistName = (string)null, 
             Name = (string)null, 
             TotalDownloads = 0, 
             TotalComments = 0, 
             TotalPlays = 0, 
             TotalLikes = 0, 
             TotalFavourites = 0, 
             WeeksDownloads = 0, 
             WeeksPlays = 0, 
             WeeksComments = 1, 
             WeeksLikes = 0, 
             WeeksFavourites = 0 
            }); 


      AddMap<AudioCounter>(counters => from counter in counters 
              where counter.Type == Core.Enums.Audio.AudioCounterType.Download 
            select new 
            { 
             Id = counter.AudioId, 
             ArtistName = (string)null, 
             Name = (string)null, 
             TotalDownloads = 1, 
             TotalComments = 0, 
             TotalPlays = 0, 
             TotalLikes = 0, 
             TotalFavourites = 0, 
             WeeksDownloads = 0, 
             WeeksPlays = 0, 
             WeeksComments = 0, 
             WeeksLikes = 0, 
             WeeksFavourites = 0 
            }); 

      AddMap<AudioCounter>(counters => from counter in counters 
              where counter.Type == Core.Enums.Audio.AudioCounterType.Play 
              select new 
              { 
               Id = counter.AudioId, 
               ArtistName = (string)null, 
               Name = (string)null, 
               TotalDownloads = 0, 
               TotalPlays = 1, 
               TotalComments = 0, 
               TotalLikes = 0, 
               TotalFavourites = 0, 
               WeeksDownloads = 0, 
               WeeksPlays = 0, 
               WeeksComments = 0, 
               WeeksLikes = 0, 
               WeeksFavourites = 0 
              }); 

      AddMap<AudioCounter>(counters => from counter in counters 
              where counter.Type == Core.Enums.Audio.AudioCounterType.Download 
              where counter.DateTime >= DateTimeOffset.Now.AddDays(-7) 
              select new 
              { 
               Id = counter.AudioId, 
               ArtistName = (string)null, 
               Name = (string)null, 
               TotalDownloads = 0, 
               TotalPlays = 0, 
               TotalComments = 0, 
               TotalLikes = 0, 
               TotalFavourites = 0, 
               WeeksDownloads = 1, 
               WeeksPlays = 0, 
               WeeksComments = 0, 
               WeeksLikes = 0, 
               WeeksFavourites = 0 
              }); 

      AddMap<Like>(likes => from like in likes 
              select new 
              { 
               Id = like.AudioId, 
               ArtistName = (string)null, 
               Name = (string)null, 
               TotalDownloads = 0, 
               TotalPlays = 0, 
               TotalComments = 0, 
               TotalLikes = 1, 
               TotalFavourites = 0, 
               WeeksDownloads = 0, 
               WeeksPlays = 0, 
               WeeksComments = 0, 
               WeeksLikes = 0, 
               WeeksFavourites = 0 
              }); 

      AddMap<Favourite>(favs => from fav in favs 
            select new 
            { 
             Id = fav.AudioId, 
             ArtistName = (string)null, 
             Name = (string)null, 
             TotalDownloads = 0, 
             TotalPlays = 0, 
             TotalComments = 0, 
             TotalLikes = 0, 
             TotalFavourites = 1, 
             WeeksDownloads = 0, 
             WeeksPlays = 0, 
             WeeksComments = 0, 
             WeeksLikes = 0, 
             WeeksFavourites = 0 
            }); 

      AddMap<AudioCounter>(counters => from counter in counters 
              where counter.Type == Core.Enums.Audio.AudioCounterType.Play 
              where counter.DateTime >= DateTimeOffset.Now.AddDays(-7) 
              select new 
              { 
               Id = counter.AudioId, 
               ArtistName = (string)null, 
               Name = (string)null, 
               TotalDownloads = 0, 
               TotalPlays = 0, 
               TotalComments = 0, 
               TotalLikes = 0, 
               TotalFavourites = 0, 
               WeeksDownloads = 1, 
               WeeksPlays = 0, 
               WeeksComments = 0, 
               WeeksLikes = 0, 
               WeeksFavourites = 0 
              }); 

      AddMap<Like>(likes => from like in likes 
            where like.DateCreated >= DateTimeOffset.Now.AddDays(-7) 
            select new 
            { 
             Id = like.AudioId, 
             ArtistName = (string)null, 
             Name = (string)null, 
             TotalDownloads = 0, 
             TotalPlays = 0, 
             TotalComments = 0, 
             TotalLikes = 0, 
             TotalFavourites = 0, 
             WeeksDownloads = 0, 
             WeeksPlays = 0, 
             WeeksComments = 0, 
             WeeksLikes = 1, 
             WeeksFavourites = 0 
            }); 

      AddMap<Favourite>(favs => from fav in favs 
             where fav.DateCreated >= DateTimeOffset.Now.AddDays(-7) 
             select new 
             { 
              Id = fav.AudioId, 
              ArtistName = (string)null, 
              Name = (string)null, 
              TotalDownloads = 0, 
              TotalPlays = 0, 
              TotalComments = 0, 
              TotalLikes = 0, 
              TotalFavourites = 0, 
              WeeksDownloads = 0, 
              WeeksPlays = 0, 
              WeeksComments = 0, 
              WeeksLikes = 0, 
              WeeksFavourites = 1 
             }); 

      Reduce = results => from result in results 
           group result by result.Id 
            into g 
            select new 
            { 
             Id = g.Key, 
             ArtistName = g.Select(x => x.ArtistName).Where(x => x != null).FirstOrDefault(), 
             Name = g.Select(x => x.Name).Where(x => x != null).FirstOrDefault(), 
             TotalDownloads = g.Sum(x => x.TotalDownloads), 
             TotalPlays = g.Sum(x => x.TotalPlays), 
             TotalComments = g.Sum(x => x.TotalComments), 
             TotalLikes = g.Sum(x => x.TotalLikes), 
             TotalFavourites = g.Sum(x => x.TotalFavourites), 
             WeeksComments = g.Sum(x => x.WeeksComments), 
             WeeksDownloads = g.Sum(x => x.WeeksDownloads), 
             WeeksPlays = g.Sum(x => x.WeeksPlays), 
             WeeksLikes = g.Sum(x => x.WeeksLikes), 
             WeeksFavourites = g.Sum(x => x.WeeksFavourites) 
            }; 
     } 

回答

2

你模特好,坚持下去。查询时您不会注意到任何性能问题,因为查询将针对预先计算的索引运行。因此,所有工作都是在服务器的后台线程中异步完成的 - 这使得查询速度更快。

另外,您不必担心索引执行中的性能,因为Map函数只能在新文档或更改文档上运行,并且Reduce函数在组中执行,因此仅计算新的地图结果。

假设这是一个我们正在讨论的网站,您将音频文档数量非规范化的替代建议会让您的介绍陷入困境,因为您每次点击某个文件时都需要加载和更新音频文档下载或播放。当然你不会注意到在一个小网站上,但如果你有一些同时访问者,这将成为一个问题。此外,这是很容易进行扩展,使用Map/Reduce的方法和AudioCounter文件,因为那样的话你需要少担心并发性和复制 - 相反,当有人下载​​或播放标题,只是把一个新的AudioCounter文档中并继续。

一件事,你应该知道的,虽然,是为期一周的计数器。如果我对他们的目标假设是真实的,那么他们现在就不会像现在这样工作。问题在于,你不能在地图/缩小索引内进行“范围聚合”(不知道正确的单词) - 它总是关于总计。为此,您可以想出一个方面查询来计算记录数量,或者使用索引复制捆绑包来填充SQL表,您可以在其中执行即席查询。我很抱歉,我没有找到一个小方法一个很好的例子,现在,也许我会放在一起一个周末...

+0

意想不到的回答再次感谢你丹尼尔。期待Facet的方法写出来...但是目前的周计数器'出现'在地图/缩小指数中工作正常,但我会听取您的建议。 – 2012-01-27 10:24:56

相关问题