我在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放在一个单独的文件中,但我不知道我的选择是什么。
答案 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();