Question

J'ai une classe de document qui contient une liste des « tags ». Quelque chose comme:

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

Maintenant, je voudrais créer une requête pour RavenDB qui me remet tous les éléments filtrés par une liste de tags. Lors de l'utilisation Entity Framework j'ai réussi à le faire par quelque chose comme ceci:

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

Toutefois, cela ne semble pas fonctionner avec RavenDB, très probablement parce que contient n'est pas supporté .. Je l'ai aussi essayé de le réécrire en utilisant tous les (Where(i => i.Tags.Any(t=>t == tag))) mais qui me donne une étrange exception:

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

Toutes les grandes idées? Est-ce que je fais cela tout à fait tort?

Était-ce utile?

La solution

est en effet pas Contains encore supporté (Peut-être qu'il devrait être, mais c'est une autre question tout à fait - nous ajoutons que vraiment le soutien de divers opérateurs lorsque son demandé)

En ce qui concerne plusieurs requêtes contre tout, je suppose que vous essayez de faire des données dynamiques et que vous voulez obtenir quelque chose comme

"X OR Y OR Z"

C'est une question délicate, et le fournisseur LINQ par défaut regroupera les multiples clauses WHERE avec ET, de sorte que votre exemple ressemble à

"X AND Y AND Z"

Ce qui sera évidemment jamais le cas.

Votre meilleure option pour celui-ci est de descendre à la requête Lucene (au moins pour l'instant) et faire quelque chose comme ceci:

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

sens?

La requête ci-dessus ressemblera à quelque chose comme

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

Note: "Tags", informe RavenDB que les balises est un tableau

D'accord, [modifier]

La meilleure façon d'obtenir ce que vous avez réellement voulez est de faire quelque chose le long de ces lignes

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

Alors pour interroger vos ands, vous pouvez faire quelque chose comme ceci:

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

Maintenant, les choses à connaître

       Tags = doc.Tags

sérialisera ce tableau entier dans un blob géant, comme il est juste des cordes qui travaillent pour cet exemple.

Je suis à la recherche de meilleures façons d'exprimer cela, il est peu probable que nous allons trouver un moyen LINQ-ish de le faire, car il ne correspond pas vraiment à travers très bien - mais est une réponse qui fonctionnera:)

Je pense que j'aimerais assez de pouvoir au moins faire

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

(Cela ne fonctionnera pas ne pas essayer), mais il est un peu plus explicite sur ce que vous voulez atteindre.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top