I have customers in RavenDB and orders associated with these customers. Currently, when attempting to use the GroupBy operation in a document query, I encounter an error in RavenDB stating that it is unable to convert the query. As a workaround, I've been using ToList() to retrieve the data into memory and then applying GroupBy, OrderBy, and Select to get the first order for each customer. However, this approach is inefficient as it is done entirely in memory.
Now, my goal is to obtain the latest orders for each customer, disregarding any date filters applied in the lookup. I attempted to achieve this by creating an OrderLookup index, but it caused RavenDB to hang and initiate indexing for the entire day without producing any results.
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
};
}
}
The first thing to understand about Map-Reduce index is that its purpose is to keep an aggregated value up-to-date at all times, as documents are added, modified, or removed.
In your case you want the index to maintain the latest order date for each customer,
with a reference to the order document.
Here is the basic implementation you are looking for:
A sample document class:
The Map-Reduce index:
The query:
Note that the output structure of the Map function must be the same as the Reduce function
(both have 'CustomerId', 'LatestDate', 'LatestOrderId' & 'LatestDocumentId')