Ravendb 按客户获取最新 orderId 组

问题描述 投票:0回答:1

我在 RavenDB 中有客户以及与这些客户关联的订单。目前,当尝试在文档查询中使用 GroupBy 操作时,我在 RavenDB 中遇到错误,指出它无法转换查询。作为解决方法,我一直使用 ToList() 将数据检索到内存中,然后应用 GroupBy、OrderBy 和 Select 来获取每个客户的第一个订单。然而,这种方法效率低下,因为它完全在内存中完成。

现在,我的目标是获取每个客户的最新订单,忽略查找中应用的任何日期过滤器。我尝试通过创建 OrderLookup 索引来实现此目的,但它导致 RavenDB 挂起并启动索引一整天而没有产生任何结果。

public class OrderLookup : AbstractIndexCreationTask<Order, OrderLookup.Results>
{
 public class Results
 {
    public string CustomerId { get; set; }
    public DateTimeOffset? MaxCreatedOn { get; set; }
    public DateTimeOffset CreatedOn { get; set; }
    public bool IsAdvancedAgreement { get; set; }
    public bool IsForecastOrder { get; set; }
    public short SoftDeleteStatus { get; set; }
    public string Id { get; set; }
}

public OrderLookup()
{
    Map = orders => from order in orders
                    select new
                    {
                        CustomerId = order.CustomerId.Id,
                        CreatedOn = order.KeyDates.CreatedOn,
                        Id = order.Id,
                        IsForecastOrder = order.IsForecastQuote,
                        SoftDeleteStatus = order.SoftDeleteStatus,
                        IsAdvancedAgreement = order.IsAdvancedAgreement
                    };

    Reduce = results => from result in results
                        orderby result.CreatedOn
                        let maxCreatedOn = results.OrderByDescending(x => x.CreatedOn)
                                                .GroupBy(x => x.CustomerId)
                                                .Select(g => g.First().CreatedOn)
                                                .First()
                        select new Results
                        {
                            CustomerId = result.CustomerId,
                            MaxCreatedOn = maxCreatedOn,
                            CreatedOn = result.CreatedOn,
                            IsAdvancedAgreement = result.IsAdvancedAgreement,
                            IsForecastOrder = result.IsForecastOrder,
                            SoftDeleteStatus = result.SoftDeleteStatus,
                            Id = result.Id
                        };
}

}

.net asp.net-web-api ravendb .net-standard ravendb5
1个回答
0
投票

关于 Map-Reduce 索引,首先要了解的是,它的目的是在添加、修改或删除文档时始终保持聚合值最新。

在您的情况下,您希望索引维护每个客户的最长日期,并参考订单文档。

这是您正在寻找的基本实现:

示例文档类:

public class MyOrder
{
    public string Id { get; set; } // document Id
    public string OrderId { get; set; }
    public string CustomerId { get; set; }
    public DateTimeOffset KeyDate { get; set; }
    public bool IsAdvancedAgreement { get; set; }
    public bool IsForecastQuote { get; set; }
    public short SoftDeleteStatus { get; set; }
}

Map-Reduce 索引:

public class MyIndex : AbstractIndexCreationTask<MyOrder, MyIndex.MyIndexEntry>
{
    public class MyIndexEntry
    {
        public string CustomerId { get; set; }
        
        public DateTimeOffset LatestDate { get; set; }
        public string LatestOrderId { get; set; }
        public string LatestDocumentId { get; set; }
    }
    public MyIndex()
    {
        Map = myOrders => from myOrder in myOrders
            select new MyIndexEntry
            {
                CustomerId = myOrder.CustomerId,
                
                LatestDate = myOrder.KeyDate,
                LatestOrderId = myOrder.OrderId,
                LatestDocumentId = myOrder.Id
            };

        Reduce = results => from result in results
            group result by result.CustomerId into g
            let latest = g.OrderByDescending(x => x.LatestDate)
            
            select new MyIndexEntry
            {
                CustomerId = g.Key,
                
                // The Map-Reduce index will keep the following updated at all times per customer
                LatestDate = latest.FirstOrDefault().LatestDate,
                LatestOrderId = latest.FirstOrDefault().LatestOrderId,
                LatestDocumentId = latest.FirstOrDefault().LatestDocumentId
            };
    }
}

查询:

using (var session = store.OpenSession())
{
    // Query the index for the customer info
    MyIndex.MyIndexEntry latestInfoAboutCustomer = session
        .Query<MyIndex.MyIndexEntry, MyIndex>()
        .Where(x => x.CustomerId == "Customer1")
        .FirstOrDefault();

    // Load the customer document
    // This document will be LATEST order for that customer
    MyOrder latestOrderOfCustomer = session.Load<MyOrder>(latestInfoAboutCustomer.LatestDocumentId);
}

注意Map函数的输出结构必须与Reduce函数
相同(两者都有'CustomerId','LatestDate'和'LatestOrderId')

© www.soinside.com 2019 - 2024. All rights reserved.