IList <t>在多地图/减少结果?</t>

时间:2011-12-26 21:12:50

标签: c# mapreduce ravendb

我正在努力使用RavenDB的多地图/减少概念,并且最近询问this question如何正确编写多地图/减少索引。

我在那个问题中得到了简单的索引,但是当我试图让它变得更复杂时,我无法使它工作。我想要做的是让索引的结果包含一个字符串列表,即:

class RootDocument {
  public string Id { get; set; }
  public string Foo { get; set; }
  public string Bar { get; set; }
  public IList<string> Items { get; set; }
}

public class ChildDocument {
  public string Id { get; set; }
  public string RootId { get; set; }
  public int Value { get; set; }
}

class RootsByIdIndex: AbstractMultiMapIndexCreationTask<RootsByIdIndex.Result> {
  public class Result {
    public string Id { get; set; }
    public string Foo { get; set; }
    public string Bar { get; set; }
    public IList<string> Items { get; set; }
    public int Value { get; set; }
  }

  public RootsByIdIndex() {
    AddMap<ChildDocument>(
      children => from child in children
        select new {
          Id = child.RootId,
          Foo = (string)null,
          Bar = (string)null,
          Items = default(IList<string>),
          Value = child.Value
      });
      AddMap<RootDocument>(
        roots => from root in roots
          select new {
           Id = root.Id,
           Foo = root.Foo,
           Bar = root.Bar,
           Items = root.Items,
           Value = 0
        });
      Reduce = 
        results => from result in results
          group result by result.Id into g
            select new {
              Id = g.Key,
              Foo = g.Select(x => x.Foo).Where(x => x != null).FirstOrDefault(),
              Bar = g.Select(x => x.Bar).Where(x => x != null).FirstOrDefault(),
              Items = g.Select(x => x.Items).Where(
                x => x != default(IList<string>).FirstOrDefault(),
                Value = g.Sum(x => x.Value)
              };
    }
}

基本上,在映射ChildDocuments和RootDocument的Items属性值时,我尝试将Items属性设置为default(IList)。但是,这不起作用。它给出了错误消息

  

请求时出错无法理解查询:

     

- 第2行第285栏:无效的Expr

     

- 第2行col 324:无法解析double .0.0

上传索引时。如何处理多地图/减少索引中的列表?

2 个答案:

答案 0 :(得分:3)

不要在索引中使用List,而是使用数组。

AddMap<ChildDocument>(
  children => from child in children
    select new {
      Id = child.RootId,
      Foo = (string)null,
      Bar = (string)null,
      Items = new string[0],
      Value = child.Value
  });
  AddMap<RootDocument>(
    roots => from root in roots
      select new {
       Id = root.Id,
       Foo = root.Foo,
       Bar = root.Bar,
       Items = root.Items,
       Value = 0
    });

Reduce = 
    results => from result in results
      group result by result.Id into g
        select new {
          Id = g.Key,
          Foo = g.Select(x => x.Foo).Where(x => x != null).FirstOrDefault(),
          Bar = g.Select(x => x.Bar).Where(x => x != null).FirstOrDefault(),
          Items = g.SelectMany(x=>x.Items),
          Value = g.Sum(x => x.Value)
          };

答案 1 :(得分:2)

David,您需要了解RavenDB使用Lucene.NET存储其索引。这意味着,您的索引中不能包含任何复杂的.net类型。

在您的示例中,我建议您使用简单的string代替IList<string>。然后,您可以加入字符串项:

AddMap<ChildDocument>(
  children => from child in children
    select new {
      Id = child.RootId,
      Foo = (string)null,
      Bar = (string)null,
      Items = (string)null,
      Value = child.Value
  });
  AddMap<RootDocument>(
    roots => from root in roots
      select new {
       Id = root.Id,
       Foo = root.Foo,
       Bar = root.Bar,
       Items = string.Join(";", root.Items),
       Value = 0
    });