2011-08-17 10 views
6

estoy usando RavenDB construir 371 y tengo el siguiente modelo:Consulta de una colección infantil para varios valores en RavenDB

class Product { 
public string Id { get; set; } 
public ProductSpec[] Specs { get; set; } 
} 

class ProductSpec { 
public string Name { get; set; } 
public string Value { get; set; } 
} 

Me gustaría ser capaz de consultar a los productos que tienen un conjunto de especificaciones. Cuando se consulta por un solo spec:

session.Query<Product>() 
.Where(product => product.Specs.Any(spec => spec.Name == "Color" && spec.Value == "Red")) 
.ToList(); 

se devuelven los resultados esperados, sin embargo, cuando se añade un predicado spec adicional:

no hay resultados se devuelven a pesar de que los resultados devueltos por la primera consulta contienen productos con nombre de especificación "País" y valor de especificación "EE. UU.". El mismo resultado se observa cuando se utiliza el método LuceneQuery. Esto parece ser un problema similar al this discussion, pero no pude implementar la solución sugerida. Específicamente, después de crear el índice sugerido, no sé cómo consultarlo.

¿Cómo puedo admitir este tipo de consulta en RavenDB?

EDITAR

Todavía no puedo consultar en múltiples valores en una colección de tipos de compuestos. En cambio, cambié el modelo para que una combinación de especificación/valor sea una cadena concatenada, de modo que la colección de especificaciones sea una matriz de cadenas. Esto puede ser consultada por los múltiples valores:

class Product { 
public string Id { get; set; } 
public int CategoryId { get; set; } 
public string[] Specs { get; set; } 
} 

Como referencia, el modelo original y consulta funciona cuando se utiliza MongoDB con su función multikeys índice. El problema más sorprendente con MongoDB es que la operación count() es slow for index queries. Este tipo de consulta es esencial para la paginación y, aunque el recuento puede almacenarse en caché, me gustaría obtener una solución que lo brinde de inmediato. Además, otro requisito que tengo es la capacidad de agregar grupos de especificaciones para colecciones arbitrarias de productos (por ejemplo, para obtener una colección de todas las combinaciones de especificaciones/valores para productos en una categoría determinada). En MongoDB esto se puede lograr utilizando su funcionalidad MapReduce; sin embargo, los resultados de una operación de MapReduce son estáticos y deben actualizarse manualmente cuando cambian los datos de origen, mientras que RavenDB actualiza los índices de MapReduce automáticamente en segundo plano. Entonces, a pesar de que declarar los índices de MapReduce en RavenDB es más engorroso que en MongoDB IMO, la actualización automática de fondo compensa los inconvenientes por una posibilidad remota. Buscaré en CouchDB ya que sus vistas también se actualizan automáticamente, aunque parece que se actualizan a pedido, no automáticamente en segundo plano, no estoy seguro de si esto será un problema.

+0

Puede ver la discusión sobre cómo resolver esto aquí: http://groups.google.com/group/ravendb/browse_thread/thread/dd8a77ccf7322c00/ab97561899624c47 –

+0

he encontrado que la sugerencia la solución funciona para colecciones de tipos simples como una matriz de cadenas, pero no funciona con un tipo compuesto como ProductSpec. La consulta no devuelve resultados. – eulerfx

Respuesta

1

He cambiado un poco el modelo y pude lograr el resultado deseado utilizando el método Project en AbstractIndexCreationTask.Este es el (simplificado) modelo de datos:

public class Product 
{ 
    public string Id { get; set; } 
    public int CategoryId { get; set; } 
    public int TotalSold { get; set; } 
    public Dictionary<string, string> Specs { get; set; } 
} 

Ésta es la definición del índice:

public class Products_ByCategoryIdAndSpecs_SortByTotalSold : AbstractIndexCreationTask<Product> 
{ 
    public Products_ByCategoryIdAndSpecs_SortByTotalSold() 
    { 
     this.Map = products => from product in products 
           select new 
           { 
            product.CategoryId, 
            _ = Project(product.Specs, spec => new Field("Spec_" + spec.Key, spec.Value, Field.Store.NO, Field.Index.ANALYZED)), 
            product.TotalSold 
           }; 
    } 
} 

Entonces puede consultar este modo:

var results = session.Advanced.LuceneQuery<Product, Products_ByCategoryIdAndSpecs_SortByTotalSold>() 
     .WhereEquals("CategoryId", 15920) 
     .AndAlso().WhereEquals("Spec_Class", "3A") 
     .AndAlso().WhereEquals("Spec_Finish", "Plain") 
     .OrderBy("-TotalSold") 
     .ToList(); 

Esto devolverá los productos de la categoría "15920" que tiene un valor de especificación "Clase" de "3A" y un valor de especificación "Finalizar" de "Normal" ordenados en orden descendente por el total de unidades vendidas.

La clave estaba usando el método Project que básicamente crea campos en el documento Lucene para cada par de nombre-valor de la especificación.

3

He intentado cosas diferentes, y tampoco he podido hacerlo funcionar. La consulta específica que está intentando ejecutar se resuelve con esta consulta Lucene por RavenDB (en la versión 426):

"{(Nombre: Color Y Valor: Rojo) Y (Nombre: País Y Valor: US)}" que explica por qué no obtienes ningún resultado.

Tras Google sobre el tema, me encontré con este post: Lucene Query Syntax

Diferentes soluciones se sugieren entre las respuestas. Espero que esto ayude Sin embargo, soy bastante curioso, si esto realmente no es posible.

Cuestiones relacionadas