我在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>()
等,但我可能需要在以后按多种类型进行过滤,这些类型将由用户动态选择。
注意:我真正想要做的是使用索引在给定某个RequestName的情况下撤回请求,但只返回RequestA(后来只返回RequestA,RequestC和RequestD)。我不想做多个查询来单独返回每个类型,我想做一个通过参数查询的查询,有时会输入。
正在设计系统,以便每个月左右添加请求类型,我们最终可能会有几百种不同的类型。我想动态搜索一组具有给定参数的特定类型。
答案 0 :(得分: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();
}
答案 1 :(得分:0)
元数据只是一个字段,因此只要它被编入索引,就可以对其进行查询。
内置索引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();