RavenDb如何在减少最终结果时将组值减少到集合中?

时间:2012-12-20 08:53:46

标签: c# linq mapreduce ravendb

我希望通过代码比标题更清楚我想做什么。基本上我正在按2个字段进行分组,并希望将结果减少到集合中所有ProductKey在Map阶段构建的集合。

public class BlockResult
{
    public Client.Names ClientName;
    public string Block;
    public IEnumerable<ProductKey> ProductKeys;
}

public Block()
{
    Map = products =>
            from product in products
            where product.Details.Block != null
            select new
            {
                product.ClientName,
                product.Details.Block,
                ProductKeys = new List<ProductKey>(new ProductKey[]{
                    new ProductKey{
                        Id = product.Id,
                        Url = product.Url
                    }
                })
            };

    Reduce = results =>
            from result in results
            group result by new {result.ClientName, result.Block} into g
            select new BlockResult
            {
                ClientName = g.Key.ClientName,
                Block =  g.Key.Block,
                ProductKeys = g.SelectMany(x=> x.ProductKeys)
            };
}

我得到一些奇怪的System.InvalidOperationException和一个源代码转储,其中基本上它试图用int(?)初始化列表。

如果我尝试用IEnumerable ProductIds替换ProductKey(并在代码中进行适当的更改)。然后代码运行但我没有在reduce中得到任何结果。

2 个答案:

答案 0 :(得分:3)

你可能不想这样做。你真的需要以这种方式查询吗?如果你知道上下文,那么你应该这样做:

var q = session.Query<Product>()
               .Where(x => x.ClientName == "Joe" && x.Details.Block == "A");

但是,要回答您的原始问题,以下索引将起作用:

public class Products_GroupedByClientNameAndBlock : AbstractIndexCreationTask<Product, Products_GroupedByClientNameAndBlock.Result>
{
    public class Result
    {
        public string ClientName { get; set; }
        public string Block { get; set; }
        public IList<ProductKey> ProductKeys { get; set; }
    }

    public class ProductKey
    {
        public string Id { get; set; }
        public string Url { get; set; }
    }

    public Products_GroupedByClientNameAndBlock()
    {
        Map = products =>
                from product in products
                where product.Details.Block != null
                select new {
                                product.ClientName,
                                product.Details.Block,
                                ProductKeys = new[] { new { product.Id, product.Url } }
                            };

        Reduce = results =>
                    from result in results
                    group result by new { result.ClientName, result.Block }
                    into g
                    select new {
                                g.Key.ClientName,
                                g.Key.Block,
                                ProductKeys = g.SelectMany(x => x.ProductKeys)
                            };
    }
}

答案 1 :(得分:0)

复制时,我得到相同的InvalidOperationException,声明它不理解索引定义(为简洁起见省略了堆栈跟踪)。

网址:“/ indexes / Keys / ByNameAndBlock” System.InvalidOperationException:无法理解查询:

我仍然不完全确定你在这里尝试了什么,所以这可能不是你想要的,但我设法让以下工作。简而言之,Map / Reduce在匿名对象中处理,因此对自定义类型的强烈输入对Raven没有任何意义。

public class Keys_ByNameAndBlock : AbstractIndexCreationTask<Product, BlockResult>
{
    public Keys_ByNameAndBlock()
    {
        Map = products =>
              from product in products
              where product.Block != null
              select new
                  {
                      product.Name,
                      product.Block,
                      ProductIds = product.ProductKeys.Select(x => x.Id)
                  };

        Reduce = results =>
                 from result in results
                 group result by new {result.Name, result.Block}
                 into g
                 select new
                     {
                         g.Key.Name,
                         g.Key.Block,
                         ProductIds = g.SelectMany(x => x.ProductIds)
                     };
    }

}

public class Product
{
    public Product()
    {
        ProductKeys = new List<ProductKey>();
    }

    public int ProductId { get; set; }
    public string Url { get; set; }
    public string Name { get; set; }
    public string Block { get; set; }
    public IEnumerable<ProductKey> ProductKeys { get; set; }
}

public class ProductKey
{
    public int Id { get; set; }
    public string Url { get; set; }
}

public class BlockResult
{
    public string Name { get; set; }
    public string Block { get; set; }
    public int[] ProductIds { get; set; }
}