RavenDB在单个属性上选择Distinct

时间:2014-05-29 20:22:57

标签: c# asp.net-mvc ravendb

我有一个存储在RavenDB中的对象,它有三个属性:ID,Score,Date。

我想创建一个索引来检索给定日期范围内的前5个分数。但是,我只想检索每个ID一条记录。如果单个ID在最高分中显示多次,我只想检索该ID的最高分,然后转到下一个ID。

示例分数:

Score____ID____
1000      1
950       1
900       1
850       2
800       2
750       3
700       4
650       5
600       6
550       7

所需的查询结果:

Score____ID____
1000      1
850       2
750       3
700       4
650       5

我创建了一个类似于此的显式索引(为简单起见而调整):

            Map = docs => from doc in docs
                      orderby doc.Score descending                          
                      select new
                        {
                            Score = doc.Score,
                            ID = doc.ID,
                            Date = doc.Date
                        };

我用类似于此的代码调用我的查询(为简单起见而调整):

                    HighScores = RavenSession.Query<Score, Scores_ByDate>()
                                                .Customize(x => x.WaitForNonStaleResultsAsOfNow())
                                                .Where(x => x.Date > StartDate)
                                                .Where(x => x.Date < EndDate)
                                                .OrderByDescending(x => x.Score)
                                                .Take(5)
                                                .ToList();

我不知道怎么说&#34;只能在列表中给我一次每个ID的结果。&#34;

2 个答案:

答案 0 :(得分:3)

所以一些指示:

  • 请勿在地图功能中订购。地图旨在将文档转储出来。
  • 使用Reduce进行分组,因为这是他们按设计工作的方式
  • 向RavenDB添加一个提示,即特定列将在代码中排序,以及它是什么类型的字段。

默认情况下,map / reduce假定排序是针对文本的,即使它是一个数字 - (I learned this the hard way并得到了帮助。)

所以..

只需将Map / Reduce索引定义为正常,并在最后添加排序条件,如下所示:

public class Score_TopScoringIndex : AbstractIndexCreationTask<Score, Score>
{
     public Score_TopScoringIndex()
     {
        Map = docs => from doc in docs
                  select new
                       {
                           Score = doc.Score,
                           ID = doc.ID,
                           Date = doc.Date
                       };

        Reduce = results => from result in results
                        group result by result.ID into g
                        select new 
                        {
                           Score = g.First().Score,
                           ID = g.Key,
                           Date = g.First().Date
                        };

        Sort(x=>x.Score, SortOptions.Int);
     }
}

通过在应用程序启动时使用来确保索引位于数据库中:

IndexCreation.CreateIndexes(typeof(Score_TopScoringIndex).Assembly, documentStore);

现在,当您查询OrderByDescending时,它会非常快。

using(var session = store.OpenSession())
{
   var highScores = session.Query<Score>("Scores/TopScoringIndex")
                       .OrderByDescending(x=>x.Score)
                       .Take(5);
}

答案 1 :(得分:-2)

您可以尝试使用morelinq库

https://code.google.com/p/morelinq/

具有DistintBy扩展名。