如何在RavenDb中查询展平子集合?需要索引?

时间:2014-01-13 03:05:37

标签: c# linq ravendb

我在C#web项目中使用RavenDb。我有一个对象,我需要查询其子集合,每个子对象1行和一些根/父对象属性 注意:这不是实际设计,只是简化了这个问题。

    public class OrderLine
    {
        public string ProductName { get; set; }
        public int Quantity { get; set; }
        public DateTime? ShipDate { get; set; }
    }
    public class Order
    {
        public int OrderId { get; set; }
        public string CustomerName { get; set; }
        public DateTime OrderDate { get; set; }
        public List<OrderLine> OrderLines { get; set; }

    }

订单行的订单是一个单独的文件。 ShipDate将在每一行上更新,因为并非所有产品都有库存。

我需要能够使用以下列创建最近发送的10个产品的列表:

OrderId
Customer
ProductName
ShipDate

这不起作用,因为不支持SelectMany:

        var query = from helper in RavenSession.Query<Order>()
                        .SelectMany(l => l.OrderLines, (order, orderline) => 
                            new { order, orderline })
                    select new 
                    {
                        helper.order.OrderId,
                        helper.order.CustomerName,
                        helper.orderline.ProductName,
                        helper.orderline.ShipDate

                    };
        var result = query.Where(x => x.ShipDate.HasValue)
            .OrderByDescending(x => x.ShipDate.Value).Take(10);

我认为正确的做法是创建一个会使列表变得扁平的索引,但我没有取得任何成功。我不相信Map-Reduce情况会起作用,因为据我了解它会有效地执行一个组,通过该组将文档数减少到较少的行(在索引中)。但在这种情况下,我试图将文档数量扩展到更多行(在索引中)。

我宁愿不把每个OrderLine放在一个单独的文件中,但我不知道我的选择是什么。

1 个答案:

答案 0 :(得分:5)

由于您希望按子类中的字段进行过滤和排序,因此您需要确保将所需的所有字段编入索引并存储

public class ShippedItemsIndex
    : AbstractIndexCreationTask<Order, ShippedItemsIndex.Result>
{
    public class Result
    {
        public int OrderId { get; set; }
        public string CustomerName { get; set; }
        public string ProductName { get; set; }
        public int Quantity { get; set; }
        public DateTime ShipDate { get; set; }
    }

    public ShippedItemsIndex()
    {
        Map = orders => 
            from order in orders
            from line in order.OrderLines
            where line.ShipDate != null
            select new
            {
                order.OrderId,
                order.CustomerName,
                line.ProductName,
                line.Quantity,
                line.ShipDate
            };

        StoreAllFields(FieldStorage.Yes);
    }
}

然后您可以project from the index进入结果。

var query = session.Query<Order, ShippedItemsIndex>()
    .ProjectFromIndexFieldsInto<ShippedItemsIndex.Result>()
    .OrderByDescending(x => x.ShipDate)
    .Take(10);

var results = query.ToList();

Here is a complete test demonstrating.