【问题标题】:Filtering by Clr-Type on a multi-map index in RavenDb在 RavenDb 中的多地图索引上按 Clr-Type 过滤
【发布时间】:2013-09-27 21:39:16
【问题描述】:

我在 RavenDb 中存储所有从基类继承的对象,并且我使用 Multi-Map 索引来搜索所有子类型,如下所示:

public class BaseRequest
{
    public Guid Id { get; set; }
    public string RequestName { get; set; }
    public DateTime RequiredDate { get; set; }
}

public class RequestA: BaseRequest
{
    public string SomethingForA { get; set; }
}

public class RequestB : BaseRequest
{
    public int SomethingForB { get; set; }
}

public class AllRequests: AbstractMultiMapIndexCreationTask
{
    public AllRequests()
    {
        AddMap<RequestA>(requests => from req in requests select new {req.RequestName, req.RequiredDate});
        AddMap<RequestB>(requests => from req in requests select new {req.RequestName, req.RequiredDate });
    }   
}

我这样搜索它:

    public BaseRequest[] Search(string requestType, string requestName, DateTime? requestDate = null) {
        var q = RavenSession.Query<BaseRequest, AllRequests>();

        if (!string.IsNullOrEmpty(requestName)) {
            q = (IRavenQueryable<BaseRequest>)Queryable.Where(q, x => x.RequestName == requestName);
        }
        if (requestDate.HasValue) {
            q = (IRavenQueryable<BaseRequest>) Queryable.Where(q, x => x.RequiredDate == requestDate);
        }

        return q.ToArray();
    }

我想做的是通过请求的 CLR-Type 进一步过滤结果。是否可以使用“Raven-Entity-Name”元数据字段来执行此操作,如果可以,如何操作?

我知道我可以只使用Query&lt;RequestA&gt;() 等,但以后可能需要按多种类型进行过滤,这些类型将由用户动态选择。

注意:我真正想做的是使用索引来拉回给定某个 RequestName 的请求,但只返回 RequestA(后来只返回 RequestA、RequestC 和 RequestD)。我不想做多个查询来单独取回每种类型,我想做一个查询,通过参数查询,有时输入。

系统的设计使得每个月左右都会添加请求类型,最终我们可能会得到几百种不同的类型。我想动态搜索一组具有给定参数的特定类型。

【问题讨论】:

    标签: polymorphism ravendb


    【解决方案1】:

    解决了。我需要使用MetadataFor(req) 将 clr 类型添加到索引中,然后使用特定的映射类型进行查询。像这样:

    public class AllRequests: AbstractMultiMapIndexCreationTask
    {
        public class SearchMap {
          public string RequestName{get;set;}
          public DateTime RequiredDate{get;set;}
          public string RequestType{get;set;}
        }
    
       public AllRequests(){
            AddMap<RequestA>(requests => from req in requests select new {req.RequestName, req.RequiredDate, RequestType = MetadataFor(req)["Raven-Clr-Type"]});
            AddMap<RequestB>(requests => from req in requests select new {req.RequestName, req.RequiredDate, RequestType = MetadataFor(req)["Raven-Clr-Type"] });
        }   
    }
    

    然后我可以查询请求的实际字段,也可以按如下类型查询:

       public BaseRequest[] Search(string requestType, string requestName, DateTime? requestDate = null) {
            var q = RavenSession.Query<AllRequests.SearchMap, AllRequests>();
    
            if (!string.IsNullOrEmpty(requestName)) {
                q = (IRavenQueryable<BaseRequest>)Queryable.Where(q, x => x.RequestName == requestName);
            }
            if (requestDate.HasValue) {
                q = (IRavenQueryable<BaseRequest>) Queryable.Where(q, x => x.RequiredDate == requestDate);
            }
    
            if (!string.IsNullOrEmpty(requestType))
            {
                q =
                    q.Where(
                        x =>
                        x.RequestType == GetClrTypeFromPassedInValue(requestType));
            }
            return q.As<BaseRequest>().ToArray();
        }
    

    【讨论】:

      【解决方案2】:

      元数据只是一个字段,只要有索引就可以查询。

      内置索引Raven/DocumentsByEntityName,如下所示:

      database.PutIndex("Raven/DocumentsByEntityName", new IndexDefinition
      {
          Map =
              @"from doc in docs 
      let Tag = doc[""@metadata""][""Raven-Entity-Name""]
      select new { Tag, LastModified = (DateTime)doc[""@metadata""][""Last-Modified""] };",
          Indexes =
          {
              {"Tag", FieldIndexing.NotAnalyzed},
          },
          Stores =
          {
              {"Tag", FieldStorage.No},
              {"LastModified", FieldStorage.No}
          }
      });
      

      然后你可以像这样查询它:

      var results = s.Advanced.LuceneQuery<RequestB>()
                      .WhereEquals("Tag", "Entity-Name")
                      .ToArray();
      

      【讨论】:

      • 是的,我知道 - 但我想做的是将它添加到我现有的强类型索引中。我找不到办法做到这一点。如果我真的需要走 LuceneQuery 路线,那么我会,但这不是我的首选解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-15
      • 1970-01-01
      • 1970-01-01
      • 2015-07-04
      • 1970-01-01
      相关资源
      最近更新 更多