RavenDb MapReduce按Id过滤

时间:2012-01-26 19:37:49

标签: .net nosql ravendb

我有最简单的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及聚集=无”,   “错误”:“System.ArgumentException:字段'__document_id'不是   indexed,无法查询未编入索引的字段\ r \ n at   Raven.Database.Indexing.Index.IndexQueryOperation.AssertQueryDoesNotContainFieldsThatAreNotIndexes()

question似乎相关。

P上。 S.我错误地删除了我以前的类似问题 - 抱歉。

更新。感谢Matt Warren建议我参与实施而不减少部分:

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 个答案:

答案 0 :(得分:3)

我不确定这个错误,但更有趣的问题是你为什么这样做呢?

我认为你有类似这样的文档:

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

当您在Id上进行分组时,您不需要Reduce部分,这是多余的。 Id字段是每个文档唯一的。实际上,您将从其父文档中提取单个投票,然后将它们分组回原来所在的组中。

<强>更新 你已经改变了一些问题,我对你要做的事情感到有点困惑。

你问

  

我喜欢这个实现,但是我必须这个令人失望的部分   即时计算评级和评论数量(我更愿意存储   索引中的这些值。

其实这可能更好。如果您将值存储在索引中,那么您将占用空间,其中包含您似乎不会查询的信息。最好只将数据存储在您实际需要查询的索引中,否则会浪费空间。

索引的转换结果部分在内存中运行,因此计算结果的速度非常快。此外,它只会在查询结果需要时计算它们,而不是每个文档。

您希望在一份Votes文档中有多少CommentsLawDisadvantage