C# RavenDb中的Map reduce超过2个集合和子集合
我在RavenDb中存储了两种不同的对象类型,它们是父/子类型关系,如JSON中所示:C# RavenDb中的Map reduce超过2个集合和子集合,c#,mapreduce,ravendb,C#,Mapreduce,Ravendb,我在RavenDb中存储了两种不同的对象类型,它们是父/子类型关系,如JSON中所示: Account/1 { "Name": "Acc1", } Items/1 { "Account": "Account/1", "Value" : "100", "Tags": [ "tag1", "tag2"] } Items/2 { "Account": "Account/1", "Value" : "50",
Account/1
{
"Name": "Acc1",
}
Items/1
{
"Account": "Account/1",
"Value" : "100",
"Tags": [
"tag1",
"tag2"]
}
Items/2
{
"Account": "Account/1",
"Value" : "50",
"Tags": [
"tag2"]
}
请注意,我不想将它们存储在同一个文档中,因为一个帐户可能有数千项
我正在尝试编写一个map/reduce索引,该索引将返回以下内容:
{
"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.所有不同标记名的列表,以及每个标记名的编号及其值
我想我需要使用多重映射来将帐户和项目集合映射到一起,但我无法找出reduce部分来创建结果的“TagInfo”部分
这是可能的,还是我在Raven中的建模都错了
编辑:
我希望从此查询中检索的类如下所示:
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;}
}
var results = session.Query<TagsWithCountAndValues.ReduceResult, TagsWithCountAndValues>()
.Where(x => x.AccountId == "accounts/1")
.ToList();
您不能为此使用多重映射/减少索引,因为您希望标记上有一个映射,而帐户上有另一个映射。它们没有公共属性,因此这里不能有多重贴图/减少 但是,您可以改用TransformResult。以下是如何做到这一点:
public class Account
{
public string Id { get; set; }
public string Name { get; set; }
}
public class Item
{
public string Id { get; set; }
public string AccountId { get; set; }
public int Value { get; set; }
public List<string> Tags { get; set; }
}
public class TagsWithCountAndValues : AbstractIndexCreationTask<Item, TagsWithCountAndValues.ReduceResult>
{
public class ReduceResult
{
public string AccountId { get; set; }
public string AccountName { get; set; }
public string Tag { get; set; }
public int Count { get; set; }
public int TotalSum { get; set; }
}
public TagsWithCountAndValues()
{
Map = items => from item in items
from tag in item.Tags
select new
{
AccountId = item.AccountId,
Tag = tag,
Count = 1,
TotalSum = item.Value
};
Reduce = results => from result in results
group result by result.Tag
into g
select new
{
AccountId = g.Select(x => x.AccountId).FirstOrDefault(),
Tag = g.Key,
Count = g.Sum(x => x.Count),
TotalSum = g.Sum(x => x.TotalSum)
};
TransformResults = (database, results) => from result in results
let account = database.Load<Account>(result.AccountId)
select new
{
AccountId = result.AccountId,
AccountName = account.Name,
Tag = result.Tag,
Count = result.Count,
TotalSum = result.TotalSum
};
}
}
公共类帐户
{
公共字符串Id{get;set;}
公共字符串名称{get;set;}
}
公共类项目
{
公共字符串Id{get;set;}
公共字符串AccountId{get;set;}
公共int值{get;set;}
公共列表标记{get;set;}
}
带有countandvalues的公共类标记:AbstractIndexCreationTask
{
公共类ReduceResult
{
公共字符串AccountId{get;set;}
公共字符串AccountName{get;set;}
公共字符串标记{get;set;}
公共整数计数{get;set;}
公共整数总和{get;set;}
}
公共标记swithCountAndValues()
{
Map=items=>来自items中的item
从item.Tags中的标记
选择新的
{
AccountId=项目。AccountId,
标签=标签,
计数=1,
TotalSum=项目价值
};
Reduce=results=>from result in results
按result.Tag对结果进行分组
进入g
选择新的
{
AccountId=g.Select(x=>x.AccountId).FirstOrDefault(),
标记=g.键,
Count=g.Sum(x=>x.Count),
TotalSum=g.Sum(x=>x.TotalSum)
};
TransformResults=(数据库,结果)=>来自结果中的结果
让account=database.Load(result.AccountId)
选择新的
{
AccountId=result.AccountId,
AccountName=account.Name,
Tag=result.Tag,
计数=结果。计数,
TotalSum=结果。TotalSum
};
}
}
然后,您可以这样查询:
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;}
}
var results = session.Query<TagsWithCountAndValues.ReduceResult, TagsWithCountAndValues>()
.Where(x => x.AccountId == "accounts/1")
.ToList();
var results=session.Query()
。其中(x=>x.AccountId==“accounts/1”)
.ToList();
好的,我找到了一种可以接受的方法,以丹尼尔的答案为基础,在这里记录下来,供未来的旅行者(可能是我自己!)
我从尝试每个帐户返回一个结果更改为每个帐户/标记组合返回一个结果,因此索引必须更改如下(注意reduce
中的groupby
位于2个属性上):
这给了我们每个帐户一个对象,以及
TagInfo
对象的子列表-每个唯一标记一个对象。谢谢Daniel,我不知道TransformResults
!但这并不是我想要的,我希望每个帐户都有一个结果,属性包含标记详细信息,请参见我的编辑。此外,上面的TotalSum不起作用,因为它对所有项目值进行求和,而不仅仅是我查询的帐户的值(我认为reduce需要按帐户分组,而不是标记?),您不能在其结果中有嵌套类的索引。我不认为你能在一个索引中得到你想要的。相反,我更希望有一些独立的索引并查询它们,以获得所需的所有信息,或者更改数据模型,使其更好地适合这种数据访问模式。好的,谢谢Daniel。我想可能是这样,但不太确定。非常感谢您抽出时间。
var hierachicalResult = from result in results
group new {result.TagName, result.TagValue} by result.AccountName
into g
select new
{
Account = g.Key,
TagInfo = g.Select(x => new { x.TagName, x.TagValue, x.TagCount })
};