c# linq ravendb

c# - Consulta de Linq con mĂșltiples Contiene/Cualquiera para RavenDB



(1)

Tengo una clase de documento que contiene una lista de "etiquetas". Algo como:

class Item { string Name { get; set; } List<string> Tags {get; set;} }

Ahora me gustaría crear una consulta para RavenDB que me entregue todos los elementos filtrados por una lista de etiquetas. Al usar Entity Framework, logré hacer esto de la siguiente manera:

var query = GetQueryable(); foreach (var tag in tags) { query = query.Where(i => i.Tags.Contains(tag)); }

Sin embargo, parece que esto no funciona con RavenDB, probablemente porque Contains no es compatible ... También he intentado reescribirlo usando Cualquiera, ( Where(i => i.Tags.Any(t=>t == tag)) ) pero eso me da una extraña excepción:

Unable to cast object of type ''System.Linq.Expressions.PrimitiveParameterExpression`1[System.String]'' to type ''System.Linq.Expressions.MemberExpression

¿Alguna gran idea? ¿Estoy haciendo esto completamente mal?


Contiene, de hecho, todavía no se admite (quizás debería serlo, pero ese es otro asunto completamente, solo agregamos soporte para varios operadores cuando se solicita)

En cuanto a las consultas múltiples contra Cualquiera, asumo que estás tratando de hacer datos dinámicos y quieres lograr algo como

"X OR Y OR Z"

Eso es complicado, y el proveedor de LINQ por defecto agregará esas múltiples cláusulas WHERE con AND, por lo que su ejemplo parece

"X AND Y AND Z"

Lo que obviamente nunca será el caso.

Su mejor opción para este es bajar a la consulta de Lucene (al menos por ahora) y hacer algo como esto:

var results = s.Advanced.LuceneQuery<Item>() .Where(string.Format("Tags,:({0})", string.Join(" OR ", tags)));

¿Tener sentido?

La consulta anterior se verá algo así como

"Tags,:(X OR Y OR Z)"

Nota: "Etiquetas" informa a RavenDB que las Etiquetas son una matriz

Está bien, [editar]!

La forma más fácil de obtener lo que realmente desea es hacer algo en este sentido

new IndexDefinition<Item, Item>() { Map = docs => from doc in docs select new { Tags = doc.Tags }, Indexes = {{ x => x.Tags, FieldIndexing.Analyzed }} }.ToIndexDefinition(store.Conventions));

Luego, para consultar tus ands, puedes hacer algo como esto:

var results = s.Advanced.LuceneQuery<Item, WhateverYouCalledThatIndex>() .Where(string.Format("Tags:({0})", string.Join(" AND ", tags)));

Ahora, cosas a tener en cuenta.

Tags = doc.Tags

Serializará toda la matriz en un blob gigante, ya que solo las cadenas funcionarán para este ejemplo.

Estoy buscando mejores formas de expresar esto, es poco probable que encontremos una forma LINQ de hacerlo, ya que no se mapea muy bien, pero es una respuesta que funcionará :)

Creo que me gustaría poder al menos hacer

Map = docs => from doc in docs select new { Tags = String.Join(" ", doc.Tags) },

(Esto no funcionará, así que no lo intentes), pero es un poco más explícito sobre lo que quieres lograr.