RavenDB - 我可以从不共享持久存在的CLR对象的应用程序创建/查询索引吗?

时间:2012-12-10 18:54:09

标签: ravendb

This帖子在某种程度上回答了这个问题(我稍后会提到答案),但我希望有更多细节。

我们有许多应用程序,每个应用程序都需要以自己的方式访问/操作Raven中的数据。数据仅通过主Web应用程序写入。其他应用程序包括批处理式任务,报告等。为了尽可能地将每个应用程序保持为解耦,它们是单独的解决方案。

在这种情况下,我如何使用我本地定义的类型从报告应用程序创建现有数据的索引?

相关问题的答案说明

  

只要您反序列化的类的结构与数据的结构部分匹配,它就不会产生影响。

     

RavenDB服务器根本不关心您在客户端中使用的类。如果你的目标是不同的平台,你当然可以共享一个dll,甚至可以共享一个便携式dll。但你是对的,没有必要。

     

但是,您应该了解Raven-Clr-Type元数据值。 RavenDB客户端在存储原始文档时设置此项。它被客户端反馈以协助反序列化,但它没有完全执行

这是我想澄清的第一部分。服务器上的文档的对象图和我的应用程序中的类型是否必须完全匹配?如果服务器上的Click文档是

{
  "Visit": {
    "Version": "0",
    "Domain": "www.mydomain.com",
    "Page": "/index",
    "QueryString": "",
    "IPAddress": "127.0.0.1",
    "Guid": "10cb6886-cb5c-46f8-94ed-4b0d45a5e9ca",
    "MetaData": {
      "Version": "1",
      "CreatedDate": "2012-11-09T15:11:03.5669038Z",
      "UpdatedDate": "2012-11-09T15:11:03.5669038Z",
      "DeletedDate": null
    }
  },
  "ResultId": "Results/1",
  "ProductCode": "280",
  "MetaData": {
    "Version": "1",
    "CreatedDate": "2012-11-09T15:14:26.1332596Z",
    "UpdatedDate": "2012-11-09T15:14:26.1332596Z",
    "DeletedDate": null
  }
}

是否有可能(如果是这样,如何?),从我的应用程序创建一个Map索引,它定义了Click类,如下所示?

class Click
{
    public Guid Guid {get;set;}
    public int ProductCode {get;set;}
    public DateTime CreatedDate {get;set;}
}

或者我的班级必须看起来像这样吗? (其中自定义类型被定义为上述文档中属性的子集,具有匹配的属性名称)

class Click
{
    public Visit Visit {get;set;}
    public int ProductCode {get;set;}
    public MetaData MetaData {get;set;}
}

更新

继续下面的答案,这是我设法开始工作的代码。

索引

public class Clicks_ByVisitGuidAndProductCode : AbstractIndexCreationTask
{
    public override IndexDefinition CreateIndexDefinition()
    {
        return new IndexDefinition
            {
                Map =
                    "from click in docs.Clicks select new {Guid = click.Visit.Guid, ProductCode = click.ProductCode, CreatedDate = click.MetaData.CreatedDate}",
                TransformResults =
                    "results.Select(click => new {Guid = click.Visit.Guid, ProductCode = click.ProductCode, CreatedDate = click.MetaData.CreatedDate})"
            };
    }
}

查询

var query = _documentSession.Query<ReportClick, Clicks_ByVisitGuidAndProductCode>()
                            .Customize(x => x.WaitForNonStaleResultsAsOfNow())
                            .Where(x => x.CreatedDate >= start.Date && x.CreatedDate < end.Date);

其中Click是

public class Click
{
    public Guid Guid { get; set; }
    public int ProductCode { get; set; }
    public DateTime CreatedDate { get; set; }
}

非常感谢@MattJohnson。

1 个答案:

答案 0 :(得分:1)

形状是部分匹配,然后它将填充它可以的位置,所以你的第二个例子可以正常工作。

但是,您可以创建一个索引来投影您在第一个示例中显示的结果。您可以根据实际要过滤或排序的任何内容进行映射,然后添加TransformResults部分:

TransformResults = (database, clicks) =>
    from click in clicks
    select new {
        click.Visit.Guid,
        click.ProductCode,
        click.MetaData.CreatedDate
    };

当您查询此索引时,它将以您在转换中指定的形状出现。这是一项名为“实时投影”的功能,您可以阅读更多有关here的内容。 (您不需要.As()来电,只需使用.Query<Click, YourIndex>(),它就可以正常使用。)

另外 - 你在做什么与MetaData是无关紧要的。 Raven保持元数据与文档分离。阅读有关元数据here的更多信息。

看起来你有版本问题。如果您只是保留审计跟踪,则应该查看Raven的标准Versioning Bundle。如果您有暂时的有效性问题,请考虑使用我的新Temporal Versioning Bundle