I have 2 different object types stored in RavenDb, which are a parent/child type relationship, like this in JSON:
Account/1
{
"Name": "Acc1",
}
Items/1
{
"Account": "Account/1",
"Value" : "100",
"Tags": [
"tag1",
"tag2"]
}
Items/2
{
"Account": "Account/1",
"Value" : "50",
"Tags": [
"tag2"]
}
Note that I don’t want to store these in the same document, as an account may have thousands of items.
I am trying to write a map/reduce index that will return me something like:
{
"Account": "Acc1",
"TagInfo": [
{ "TagName" : "tag1",
"Count" : "1", //Count of all the "tag1" occurrences for acc1
"Value" : "100" //Sum of all the Values for acc1 which are tagged 'tag1'
},
{ "TagName" : "tag2",
"Count" : "2", //Two items are tagged "tag2"
"Value" : "150"
}]
}
i.e. a list of all the distinct tag names along with the number of each and their value.
I think I need to use a multi-map to map the Account and Items collections together, but I can’t figure out the reduce part to create the “TagInfo” part of the result.
Is this possible, or am I modelling this all wrong in Raven?
EDIT:
The class I want to retrieve from this query would look something like this:
public class QueryResult
{
public string AccountId {get;set;}
public TagInfo Tags {get;set;}
}
public class TagInfo
{
public string TagName {get;set;}
public int Count {get;set;}
public int TotalSum {get;set;}
}
OK, so I figured out a way to do this in an acceptable manner that builds on Daniel’s answer, so I’ll record it here for any future travellers (probably myself!).
I changed from trying to return one result per account, to one result per account/tag combination, so the index had to change as follows (note the
group byin thereduceis on 2 properties):As before, querying this is just:
The result of this can then be transformed into the object I originally wanted by an in-memory LINQ query. At this point the number of results that could be returned would be relatively small, so performing this at the client end is easily acceptable. The LINQ statement is:
Which gives us one object per account, with a child list of
TagInfoobjects – one for each unique tag.