Filtrado por Clr-Type en un índice de mapas múltiples en RavenDb

Estoy almacenando objetos en RavenDb que todos heredan de una clase base y estoy usando un índice Multi-Map para buscar en todos los subtipos como este:

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 });
    }   
}

Y lo busco así:

    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();
    }

Lo que me gustaría hacer es filtrar aún más los resultados por el tipo CLR de la solicitud. ¿Es posible hacer esto con el campo de metadatos "Raven-Entity-Name" y, de ser así, cómo?

Sé que podría usar Query<RequestA>() etc., pero es probable que necesite filtrar por varios tipos en una fecha posterior y estos tipos serán elegidos dinámicamente por el usuario.

Nota: Lo que realmente quiero hacer es usar el índice para recuperar las Solicitudes dadas un determinado Nombre de Solicitud, pero solo devolver las Solicitudes A (y luego solo Solicitudes A, Solicitudes C y Solicitudes D). No quiero hacer consultas múltiples para recuperar cada tipo individualmente, quiero hacer la única consulta que consulta por los parámetros y, a veces, escribe.

El sistema está siendo diseñado para que los tipos de solicitudes se agreguen cada mes y probablemente terminaremos con un par de cientos de tipos diferentes. Me gustaría buscar dinámicamente un conjunto de tipos específicos con parámetros dados.

preguntado el 22 de mayo de 12 a las 12:05

2 Respuestas

Lo resolvió. necesitaba usar MetadataFor(req) para agregar el tipo clr al índice y luego usar un tipo de mapa específico para consultar. Como esto:

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"] });
    }   
}

Luego puedo consultar los campos reales de la Solicitud, y también por tipo como este:

   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();
    }

contestado el 22 de mayo de 12 a las 16:05

Los metadatos son solo un campo, por lo que siempre que estén indexados, puede consultarlos.

El índice incorporado Raven/DocumentsByEntityName, Se ve como esto:

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}
    }
});

A continuación, puede consultarlo así:

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

Respondido el 27 de Septiembre de 13 a las 14:09

Sí, lo sé, pero lo que me gustaría hacer es agregarlo a mi índice de tipo fuerte existente. No puedo encontrar una manera de hacer eso. Si realmente necesito seguir la ruta de LuceneQuery, lo haré, pero no es mi solución preferida. - russell troywest

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.