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.