Domanda

ho una classe di documento che contiene un elenco di "tag". Qualcosa di simile:

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

Ora vorrei creare una query per RavenDB che mi porge tutti gli elementi filtrati da un elenco di tag. Quando si utilizza Entity Framework sono riuscito a fare questo da qualcosa di simile a questo:

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

Tuttavia, questo non sembra funzionare con RavenDB, molto probabilmente perché contiene non è supportato .. Ho anche provato riscrittura utilizzando qualsiasi, (Where(i => i.Tags.Any(t=>t == tag))), ma che mi dà una strana eccezione:

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

Tutte le grandi idee? Me lo fa fare completamente sbagliato?

È stato utile?

Soluzione

Contiene è infatti non è ancora supportato (forse dovrebbe essere, ma questa è un'altra faccenda - abbiamo solo aggiungere il supporto per diversi operatori quando la sua chiesto)

Per quanto riguarda più query contro qualsiasi, presumo che stai cercando di fare dei dati dinamici e si vuole raggiungere qualcosa di simile

"X OR Y OR Z"

Questo è un ingannevole, e il provider LINQ per default sarà aggregare coloro multipla clausole WHERE con E, così il vostro esempio appare come

"X AND Y AND Z"

che ovviamente non è il caso.

La soluzione migliore per questo è di discesa alla query Lucene (almeno per ora) e fare qualcosa di simile a questo:

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

ha senso?

La query sopra sarà simile

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

Nota: "Tag", informa che RavenDB Tag è un array

D'accordo, [modifica]!

Il modo più semplice per ottenere quello che in realtà volete è quello di fare qualcosa in questo senso

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

Poi, per query per i vostri ands, si può fare qualcosa di simile:

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

Ora, le cose di essere a conoscenza di

       Tags = doc.Tags

Sarà serializzare che l'intero array in un blob gigante, in quanto è solo stringhe che lavorerà per questo esempio.

Sto cercando di modi migliori per esprimere questo, è improbabile che verremo con un modo LINQ-ish di fare questo, come in realtà non la mappa in tutto molto bene - ma è una risposta che funzionerà:)

Penso che mi piace molto essere in grado di fare almeno

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

(Questo non funziona in modo da non provare), ma è un po 'più esplicito su ciò che si vuole raggiungere.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top