RavenDb MapReduce фильтр по идентификатору - PullRequest
0 голосов
/ 26 января 2012

У меня самый простой индекс MapReduce:

    public class LawDisadvantageRatingIndex : AbstractIndexCreationTask<LawDisadvantage, LawDisadvantageRatingIndex.IndexResult>
    {
        public class IndexResult
        {
            public string Id { get; set; }
            public long Value { get; set; }
        }

        public LawDisadvantageRatingIndex()
        {
            Map = (lawDisadvantages => from lawDisadvantage in lawDisadvantages
                                       from vote in lawDisadvantage.Votes
                                       select
                                           new
                                               {
                                                   Id = lawDisadvantage.Id,
                                                   Value = vote.Value,
                                               });

            Reduce = (lawDisadvantages => from lawDisadvantage in lawDisadvantages
                                          group lawDisadvantage by lawDisadvantage.Id
                                          into agg
                                          select new
                                                     {
                                                         Id = agg.Key,
                                                         Value = agg.Sum(x => x.Value)
                                                     });
        }
}

Вот типичный запрос:

_documentSession.Query<LawDisadvantageRatingIndex.IndexResult, LawDisadvantageRatingIndex>().Single(x => x.Id == lawDisadvantageId);

Когда я запрашиваю его с фильтрацией по Id, я получаю следующее исключение:

"URL": "/ Индексов / LawDisadvantageRatingIndex? Запрос = __ document_id% 253ALawDisadvantages% 252F1 & начать = 0 & PAGESIZE = 2 & агрегацию = None", «Ошибка»: «System.ArgumentException: поле« __document_id »не является индексируется, не может запрашивать поля, которые не проиндексированы \ r \ n в Raven.Database.Indexing.Index.IndexQueryOperation.AssertQueryDoesNotContainFieldsThatAreNotIndexes ()

Этот вопрос представляется актуальным.

P. S. Я удалил свой предыдущий аналогичный вопрос по ошибке - извините за это.

Обновление. Спасибо Мэтту Уоррену за то, что я пришел к реализации без уменьшения части:

public class LawDisadvantagesForListIndex : AbstractIndexCreationTask<LawDisadvantage>
{
    public class IndexResult
    {
        public string Id { get; set; }
   }

    public class LawDisadvantageForList
    {
        public string Id { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public long Rating { get; set; }
        public long CommentsCount { get; set; }
    }

    public LawDisadvantagesForListIndex()
    {
        Map = lawDisadvantages => from lawDisadvantage in lawDisadvantages
                                  select new { Id = lawDisadvantage.Id };

        TransformResults = (database, lawDisadvantages) => from lawDisadvantage in lawDisadvantages
                                                       select new
                                                                  {
                                                                      Id = lawDisadvantage.Id,
                                                                      Title = lawDisadvantage.Title,
                                                                      Description = lawDisadvantage.Description,
                                                                      Rating = lawDisadvantage.Votes.Sum(x => x.Value),
                                                                      CommentsCount = lawDisadvantage.Comments.Count
                                                                  };
    }
}

Вот типичное использование:

 var lawDisadvantages =
                _documentSession.Query<LawDisadvantagesForListIndex.IndexResult, LawDisadvantagesForListIndex>().
                    As<LawDisadvantagesForListIndex.LawDisadvantageForList>().
                    ToList();

Мне нравится эта реализация, но разочаровывающая часть заключается в том, что я должен вычислять Rating и CommentsCount на лету (я бы предпочел хранить эти значения в индексе).

P. S. Я все еще думаю, что в RavenDb есть ошибка, связанная с моим первым индексом.

1 Ответ

3 голосов
/ 27 января 2012

Я не уверен насчет ошибки, но более интересный вопрос - почему вы вообще так делаете?

Я полагаю, у вас есть документы, которые выглядят примерно так:

public class LawDisadvantage
{
    public string Id { get; set; }
    public List<Vote> Votes { get; set; }
    ....
}

public class Vote
{
    public int Value
    ....
} 

Если вы просто сделаете свой индекс следующим образом:

public LawDisadvantageRatingIndex()
{
       Map = (lawDisadvantages => from lawDisadvantage in lawDisadvantages
                            select new
                              {
                                   Id = lawDisadvantage.Id,
                                   ValueSum = vote.Values.Sum()
                              });
}

Вам не нужна часть Reduce, поскольку вы группируете на Id, что является избыточным. Поле Id является уникальным для каждого документа. Фактически вы извлекаете отдельные голоса из родительского документа, а затем группируете их в те же группы, в которых они были изначально.

Обновление Вы немного изменили свой вопрос, и я немного озадачен тем, что вы пытаетесь сделать.

Вы спрашиваете

Мне нравится эта реализация, но разочаровывающая часть в том, что я должен рассчитывать рейтинг и коментарии на лету (предпочел бы хранить эти значения в индексе).

На самом деле это, вероятно, предпочтительнее. Если вы сохранили значения в индексе, вы бы заняли место с информацией, к которой вы не обращаетесь. Лучше хранить данные только в том индексе, к которому вам действительно нужно запросить, иначе это пустое пространство.

Секция результатов преобразования индекса работает в памяти, и поэтому будет очень быстро вычислять результаты. Кроме того, он будет рассчитывать их только тогда, когда они нужны для результата запроса, а не для каждого документа.

Сколько Votes и Comments вы ожидаете иметь в одном LawDisadvantage документе?

...