我正在开发一个在后端使用RavenDB的应用程序。这是我第一次使用Raven,我正在为Map/Reduce而挣扎。
我一直在读医生的书,但不幸的是,在这个过程中我没有取得任何进展。
基本上我有成千上万这样的文件。
{
.....
"Severity": {
"Code": 6,
"Data": "Info"
},
"Facility": {
"Code": 16,
"Data": "Local Use 0 (local0)"
},
.....
}
除此之外,我需要制作一个输出如下的单个查询。
{"Severity": [
{"Emergency":0},
{"Alert":0},
{"Critical":0},
{"Error":0},
{"Warning":0},
{"Notice":0},
{"Info":2711},
{"Debug":410}
],
"Facility": [
{"Kernel Messages":0},
{"User-Level Messages":0},
{"Mail System":0},
{"System Daemons":0},
{"Security/Authorization Messages":0},
{"Internal Syslogd Messages":0},
{"Line Printer Subsystem":2711},
{"Network News Subsystem":410},
....
{"Local Use 0 (local0)": 2574},
...
]}
其中,严重性/设施数组中的"Key"是上述json数据的Data
部分,而严重性/设备数组的"value"是每个Code
类型的文档Count
。
示例:
以上述数据为指导,
我的数据库中有2711个文档的严重性为
Info
我的数据库中有410个文档的严重性为Debug
我的数据库中有2574个文档,使用local0
功能
等等。
我想做的是在应用程序启动时生成适当的索引(或者检查它们是否已经存在),但我甚至不知道从哪里开始。
注意:应用程序需要生成索引,仅仅手动将其写入RavenDBWebUI是不够的。
您需要结合多种技术来实现这一点,但这是非常可行的。
这是一个对你来说应该很有用的索引。
public class MyIndex : AbstractMultiMapIndexCreationTask<MyIndex.ReduceResult>
{
public class ReduceResult
{
public string Source { get; set; }
public string Code { get; set; }
public string Data { get; set; }
public int Count { get; set; }
}
public MyIndex()
{
AddMap<MyDoc>(docs => from doc in docs
select new
{
Source = "Severity",
doc.Severity.Code,
doc.Severity.Data,
Count = 1
});
AddMap<MyDoc>(docs => from doc in docs
select new
{
Source = "Facility",
doc.Facility.Code,
doc.Facility.Data,
Count = 1
});
Reduce = results => from result in results
group result by new { result.Source, result.Code }
into g
select new
{
g.Key.Source,
g.Key.Code,
g.First().Data,
Count = g.Sum(x => x.Count)
};
TransformResults = (database, results) =>
from result in results
group result by 0
into g
select new
{
Severity = g.Where(x => x.Source == "Severity")
.ToDictionary(x => x.Data, x => x.Count),
Facility = g.Where(x => x.Source == "Facility")
.ToDictionary(x => x.Data, x => x.Count)
};
}
}
您还需要一个用于转换结果的容器类:
public class MyDocCounts
{
public IDictionary<string, int> Severity { get; set; }
public IDictionary<string, int> Facility { get; set; }
}
你可以这样查询:
var result = session.Query<MyIndex.ReduceResult, MyIndex>()
.As<MyDocCounts>()
.ToList().First();
.ToList()
可能看起来是多余的,但它是必要的,因为我们在转换中进行分组。
这里有一个完整的单元测试。其输出如下:
{
"Severity": {
"AAA": 20,
"BBB": 20,
"CCC": 20,
"DDD": 20,
"EEE": 20
},
"Facility": {
"FFF": 20,
"GGG": 20,
"HHH": 20,
"III": 20,
"JJJ": 20
}
}