Pregunta

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 con algo como esto:

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

Sin embargo, esto no parece funcionar con RavenDB, probablemente porque Contiene no es compatible.También intenté reescribirlo usando Any, (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 buena idea?¿Estoy haciendo esto completamente mal?

¿Fue útil?

Solución

De hecho, Contiene aún no es compatible (tal vez debería serlo, pero ese es otro asunto completamente diferente: en realidad solo agregamos soporte para varios operadores cuando se solicita)

En cuanto a las consultas múltiples contra Any, supongo que está intentando generar datos dinámicos y desea lograr algo como

"X OR Y OR Z"

Esto es complicado, y el proveedor LINQ de forma predeterminada agregará esas múltiples cláusulas WHERE con AND, por lo que su ejemplo se verá así

"X AND Y AND Z"

Lo cual obviamente nunca será el caso.

Su mejor opción para esta 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á así

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

Nota:"Etiquetas", informa a RavenDB que Etiquetas es una matriz

¡Está bien, [editar]!

La forma más fácil de conseguir lo que realmente desear 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 bien, cosas a tener en cuenta

       Tags = doc.Tags

Serializará toda esa matriz en una mancha gigante, ya que son solo cadenas las que funcionarán para este ejemplo.

Estoy buscando mejores formas de expresar esto, es poco probable que se nos ocurra una forma similar a LINQ de hacerlo, ya que en realidad no se relaciona 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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top