RavenDB Select Distinct для одного свойства

У меня есть объект, хранящийся в RavenDB с тремя свойствами: ID, Score, Date.

Я хочу создать индекс для получения 5 лучших результатов в указанном диапазоне дат. Однако я хочу получить только одну запись для каждого идентификатора. Если один из идентификаторов появляется более одного раза в верхних баллах, я хочу получить только самый высокий балл для этого идентификатора, а затем перейти к следующему идентификатору.

пример оценки:

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();

Я не знаю, как сказать "дайте мне результаты каждого удостоверения личности один раз в списке".

2 ответа

Решение

Итак, несколько указателей:

  • Не заказывайте в функции карты. Карты предназначены только для выгрузки документов.
  • Используйте Сокращение, чтобы сделать группировку, поскольку это - способ, которым они работают проектно
  • Добавьте в RavenDB подсказку, что конкретный столбец будет отсортирован в коде, и какой это тип поля.

По умолчанию карта / уменьшение предполагает, что сортировка предназначена для текста, даже если это число - ( я научился этому нелегко и получил помощь для этого.)

Так..

Просто определите индекс 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);
}

Вы можете попробовать использовать библиотеку morelinq

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

который имеет расширение DistintBy.

Другие вопросы по тегам