C# 使用C查询RavenDB中的组合键集合#

C# 使用C查询RavenDB中的组合键集合#,c#,ravendb,C#,Ravendb,我在RavenDB收藏了这门课 public class Report { public string User { get; set; } public int Quarter { get; set; } public int Year { get; set; } public string ReportData { get; set; } } 每个用户每年每个季度只有一份报告(因此识别键为{user,quarty,year}。我想创建一个函数来保存这些报告的

我在RavenDB收藏了这门课

public class Report
{
    public string User { get; set; }
    public int Quarter { get; set; }
    public int Year { get; set; }
    public string ReportData { get; set; }
}
每个用户每年每个季度只有一份报告(因此识别键为
{user,quarty,year}
。我想创建一个函数来保存这些报告的列表,根据需要覆盖旧报告或插入新报告。我提出了以下建议:

public void Save(IList<Report> reports)
{
    session.Query<Report>()
        .Join(reports,
            x => new { x.User, x.Quarter, x.Year },
            y => new { y.User, y.Quarter, y.Year },
            (x, y) => new { OldReport = x, NewReport = y })
        .ForEach(report =>
        {
            if (report.OldReport != null)
                report.OldReport.InjectFrom(report.NewReport);
            else
                session.Store(report.NewReport);
        });

    session.SaveChanges();
}
公共作废保存(IList报告)
{
session.Query()
.加入(报告、,
x=>新{x.用户,x.季度,x.年度},
y=>新{y.用户,y.季度,y.年度},
(x,y)=>new{OldReport=x,NewReport=y})
.ForEach(报告=>
{
如果(report.OldReport!=null)
report.OldReport.InjectFrom(report.NewReport);
其他的
session.Store(report.NewReport);
});
session.SaveChanges();
}
但是,RavenDB不支持
.Join
操作符。编辑:我刚刚意识到,这也需要是一个正确的外部连接才能工作,但我认为它传达了我的意图。我知道我需要做一些Map Reduce来实现这一点,但我是RavenDB的新手,我找不到任何与此相关的好例子我正在做。有人试过这样的东西吗


另外,
.InjectFrom()
操作使用的是
Omu.ValueInjecter
,如果有人想知道的话。

有多种方法可以做到这一点,但最简单的方法是提供您自己的文档密钥,而不是使用Raven生成的一个。这通常被称为使用“结构化”或“语义”密钥

只需向类中添加一个字符串
Id
属性。您希望文档键反映您描述的唯一键,因此它可能应该有一个值,例如
“reports/2013/Q1/bob”
(但您可能希望
user
有一个更唯一的值)

您可以让.Net在属性getter中为您构造密钥,例如:

public class Report
{
    public string Id
    {
      get { return string.Format("reports/{0}/Q{1}/{2}", Year, Quarter, User); }
    }

    public string User { get; set; }
    public int Quarter { get; set; }
    public int Year { get; set; }
    public string ReportData { get; set; }
}
现在,当您存储这些文档时,只需存储它们:

foreach (var report in reports)
    session.Store(report);
如果已存在具有相同密钥的文档,则该文档将被新数据覆盖。否则,将写入新文档

如果您无法操作文档密钥,您可以研究的其他技术包括:

  • 您可以先运行查询以删除与更改的数据相匹配的任何文档。然后可以插入所有数据。但由于要匹配多个字段,因此很难正确执行查询。这是可能的,但该技术具有挑战性

  • 您可以使用来操作已存储文档的数据。尽管您仍然需要查询以确定哪些是新插入的,哪些是更新的。此外,修补程序还必须针对整个数据库进行测试,因此速度会很慢

我相信还有一些其他的想法,但最安全、最简单的方法是使用报表的语义键