查询和/或加载文档后从RavenDB获取聚合数据

时间:2013-06-05 16:27:26

标签: ravendb

我有以下文档模型:

public class Product
{
    public int Id {get;set;}
    public string Name {get;set;}
    // ...
}

public class Customer
{
    public int Id {get;set;}
    public string Name {get;set;}
    // ...
}

public class ProductOrder
{
    public int Id {get;set;}
    public int ProductId {get;set;}
    public int CustomerId {get;set;}
    public int Quantity {get;set;}
    // ...
}

在查询Product时,我还希望拥有订购产品(Quantity)和唯一客户的数量。对于Customer,我想获得订购产品的数量。

如何使用RavenDB实现这一目标?使用索引我只有Load<>另一个实体的可能性,而不是所有引用我查询的实体的实体。

由于产品的订单数量可能非常高,我没有将它们添加到Product文档中,因此在使用Include<>编制索引时我无法访问订单或LoadDocument<>

我的模型对于DocumentDB是错误的还是有另一种获取这些信息的方法?如果是这样,如何更好地做到这一点?

感谢。

更新

以下是订单数量的索引:

public class ProductOrder_CountByProduct : AbstractIndexCreationTask<ProductOrder, ProductOrder_CountByProduct.Result>
{
    public class Result
    {
        public int ProductId { get; set; }
        public int NumberOfOrders { get; set; }
    }

    public ProductOrder_CountByProduct()
    {
        Map = orders => from order in orders
                          select new
                                     {
                                         ProductId = order.ProductId,
                                         NumberOfOrders = order.Quantity
                                     };

        Reduce = results => from result in results
                            group result by result.ProductId
                            into g
                            select new
                                       {
                                           ProductId = g.Key,
                                           NumberOfOrders = g.Sum(p => p.NumberOfOrders)
                                       };
    }
}

现在我可以按产品ID获取订单数量:

var result = documentSession.Query<ProductOrder_CountByProduct.Result, ProductOrder_CountByProduct>()
                            .FirstOrDefault(p => p.ProductId == product.Id)
                            ?? new ProductOrder_CountByProduct.Result();

var count = result.NumberOfOrders;

CountByCustomer查询/索引相同。 到目前为止,Product的单个结果非常好。

但我的目标是查询产品(按名称或描述)并填写以下数组:

public class ProductViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    public int NumberOfOrders { get; set; }
    public int NumberOfCustomers { get; set; }

    //... maybe NumberOfCustomersFromUSA, etc.
}

使用CountByProductCountByCustomer索引,我需要迭代产品查询的每个结果,并对每个结果执行2 CountByXY个查询。

这是要走的路吗?

1 个答案:

答案 0 :(得分:1)

你真的不想为每个项目打电话。这是一个“选择N + 1”问题。 Raven实际上会阻止你这样做,将你在单个会话中可以提出的请求数限制为30个。

您可以使用一些不同的技术。

选项1

如果您希望能够查询名称和说明字段:

  • 在索引图中包含名称和说明。
  • 将它们包含在reduce键中,并将其传递给未修改的。
  • 然后,您可以将它们包含在查询的Where谓词中。

选项2

如果您只想在输出中输入名称和说明字段,但不想按其查询:

  • 向索引添加TransformResults步骤。
  • 在转换中,按照您按其分组的ID加载产品。
  • 返回已加载产品的名称和说明字段以及原始汇总计数。

选项3

与选项2相同的情况,但您可以在没有转换的情况下执行此操作

  • 查询时,请在查询自定义中指定Include
  • 当您遍历结果时,您可以加载产品详细信息而无需实际访问服务器,因为它们已包含在内。详细了解包含here

选项4

您可能需要考虑使用Indexed Properties Bundle将这些查询的结果写回产品文档的属性。这样,您只需查询产品,您的数据就在一个地方 - 即使它们聚合在多个索引中。

-

您可能希望结合上述多种技术,例如 - 您可能希望在查询中包含产品名称,以便您可以通过它进行查询,但您可能希望仅显示产品说明,以便转换查询结果返回它。

你说的一件事听起来并不是很正确。为什么要在产品视图模型中返回客户数量?除非“订购此产品的客户数量” - 然后它可能不属于那里。