如何在C#中为RavenDB正确创建Map / Reduce索引

我正在开发一个在后端使用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}, ... ]} 

因此,Severity / Facility Array中的“Key”是上述json数据的Data部分,Severity / Facility Array中的“value”是每个Code类型的文档Count

例:
以上述数据为指导,

我的数据库中有2711个文档,其中包含Info严重性。
我的数据库中有410个文档,其中包含Debug严重性。
我的数据库中有2574个文档,其中包含local0工具。
等等…


我想做的是在应用程序启动时生成适当的索引(或检查它们是否已存在),但我甚至不知道从哪里开始。

注意:应用程序需要生成索引,仅仅手动将其写入RavenDB Web UI是不够的。

您需要结合几种技术来实现这一目标,但这是非常可行的。

这是一个应该适合你的索引。

 public class MyIndex : AbstractMultiMapIndexCreationTask { 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(docs => from doc in docs select new { Source = "Severity", doc.Severity.Code, doc.Severity.Data, Count = 1 }); AddMap(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 Severity { get; set; } public IDictionary Facility { get; set; } } 

您可以这样查询:

 var result = session.Query() .As() .ToList().First(); 

.ToList()似乎是多余的,但它是必要的,因为我们在转换中进行分组。

这里有完整的unit testing。 输出如下:

 { "Severity": { "AAA": 20, "BBB": 20, "CCC": 20, "DDD": 20, "EEE": 20 }, "Facility": { "FFF": 20, "GGG": 20, "HHH": 20, "III": 20, "JJJ": 20 } }