RavenDB: How to do a simple map/reduce aggregation
Ok given a collection of documents like this:
{
"Name": "A开发者_Python百科",
"Price": 1.50
}
How do I perform a simple aggregation on the prices in the list? I don't want to perform any grouping, just a simple scalar result.
ie. sum, avg etc
I have tried both of the following without success:
Map only:
for doc in docs
select new { sumPrices = Sum(d => d.Price) }
and
Map:
for doc in docs
select new { price = d.Price }
Reduce:
for result in results
select new { sumPrices = Sum(result) }
This should do the trick.
Map:
from doc in docs.Products
select new { Name = "Total", Total = doc.Price }
Reduce:
select new
{
Name = g.Key,
Total = g.Sum(x => (double)x.Total)
}
Each doc goes through the Map, and the aggregation happens in the Reduce. But the schema coming out of the Map still needs to match your result. The "Total" for each document is just its Price. These all then get summed in the reduce.
The Name property is kind of useless, its just there to give the reduce something to group every single document on.
Here's what I came up with.
Map:
from doc in docs
where doc["@metadata"]["Raven-Entity-Name"] == "Books"
select new { Name = "Total", Price = doc.Price };
Reduce:
from result in results
group result by result.Name
into g
select new { Name = g.Key, Price = g.Sum(x => x.Price) }
However, I was only able to get this to work if I changed the price to an integer. So my two docs look like this:
{
"Name":"B",
"Price":4
}
{
"Name":"A",
"Price":10
}
And my JSON output looks like this:
{"Results":[{"Name":"Total","Price":"14","Price_Range":"14"}],"IsStale":false,"TotalResults":1}
Obviously, changing the price to integers is not the solution. It may be a bug in RavenDB, but I'm pretty new to it myself, so I'm hoping it's just the way I'm doing my Sum()
or the way that the data is represented in the document.
精彩评论