5

我在 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<RequestA>()etc,但以后可能需要按多种类型进行过滤,并且这些类型将由用户动态选择。

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

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

4

2 回答 2

2

解决了。我需要使用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();
    }
于 2012-05-22T15:02:16.053 回答
1

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

内置 index 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();
于 2012-05-22T13:52:43.277 回答