3 votes

Raven DB LINQ Where->Any Query ne fonctionne pas

J'obtiens un (non-)résultat bizarre de la part de Raven DB.

J'utilise la dernière version stable, v2.5.2666, à la fois sur le client et sur le serveur.

Ce que je veux récupérer est "le premier document DeployProject qui contient un objet Component dont la valeur Id est 'x'".

La première chose que j'ai essayée est donc.. :

var project = _documentSession.Query<DeployProject>()
      .FirstOrDefault(i=>i.ComponentList.Any(j=>j.Id == componentId));

Mais le résultat est nul, même si je sais que les données sont correctes. Pour vérifier que je ne suis pas fou, j'ai ajouté un .ToList() à middle, afin qu'il puisse extraire tous les documents en mémoire et les interroger à cet endroit.

var project = _documentSession.Query<DeployProject>()
      .ToList()
      .FirstOrDefault(i=>i.ComponentList.Any(j=>j.Id == componentId));

Et cela a fonctionné, donc ma logique et mes données sont correctes. Mais bien sûr, c'est vraiment inefficace, l'idée étant que je ne veux extraire que le document unique qui contient l'enregistrement de l'enfant concerné.

Il semble donc qu'il y ait un problème avec la façon dont Raven interroge l'index, puisque les données sont bien là, et que je peux les récupérer si je mets tout en mémoire et que j'exécute la même requête LINQ.

J'espérais (craignais ?) que l'index était périmé, et je lui ai donc demandé de me fournir des données fraîches :

var project = _documentSession.Query<DeployProject>()
      .Customize(i=>i.WaitForNonStaleResultsAsOfLastWrite())
      .FirstOrDefault(i=>i.ComponentList.Any(j=>j.Id == componentId));

Mais une fois de plus, j'ai été nul. Il semble que Raven ne traite pas la déclaration LINQ de la manière dont je m'y attendrais, c'est-à-dire de la manière dont LINQ to objects fonctionnerait. Je sais qu'il peut y avoir des différences, mais il devrait s'agir d'une requête assez simple qui devrait fonctionner.

Quelqu'un a-t-il une idée ? Ai-je raté quelque chose de simple ?

EDIT : D'après la documentation de Raven, il semble que cela devrait fonctionner sans indexation aventureuse :

http://ravendb.net/docs/client-api/querying/using-linq-to-query-ravendb

Outre la clause Where, il existe plusieurs autres opérateurs utiles que vous pouvez utiliser pour filtrer les résultats.

Any peut être utilisé sur des collections d'objets (ou des listes primitives) dans votre pour ne renvoyer que ceux qui satisfont une condition. RavenDB supporte également supporte également un opérateur In, pour faciliter les comparaisons inverses de Any :

// Return only companies having at least one employee named "Ayende"
IQueryable<Company> companies = from c in session.Query<Company>()
                                where c.Employees.Any(employee => employee.Name == "Ayende")
                                select c;

1voto

Hogan Points 30189

Je pense qu'il s'agit probablement d'un problème de type, c'est moche mais avez-vous essayé ceci ?

var project = _documentSession.Query<DeployProject>()
  .Where(i=>i.ComponentList.Any(j=>j.Id.ToString() == componentId.ToString()))
  .FirstOrDefault();

Si cela fonctionne, la requête originale compare deux types différents et ne convertit pas correctement l'un d'entre eux.


Essayez ceci, voyez si vous obtenez ce que vous attendez...

var project = _documentSession.Query<DeployProject>()
      .Where(i=>i.ComponentList.Any(j=>j.Id == componentId))
      .FirstOrDefault();

Je sais que cela devrait être la même chose, mais vous pouvez le tester comme ceci avec le débogueur pour voir ce qui est retourné :

var project = _documentSession.Query<DeployProject>()
      .Where(i=>i.ComponentList.Any(j=>j.Id == componentId))
      .ToList()
      .FirstOrDefault();

0voto

Wyatt Barnett Points 12541

Tout d'abord, les sous-sélections ne sont pas vraiment simples - il s'agit d'une requête très complexe du point de vue de raven / LINQ. Je regarderais l'index ad-hoc qui a été créé et je verrais s'il fonctionne vraiment.

Une meilleure approche consisterait à créer un index. Les deux approches qui me viennent à l'esprit seraient de construire un index groupé par componentId avec les projets de déploiement listés. Une autre approche consisterait à construire un index de type texte intégral avec l'ID de composant inclus, ce qui permettrait d'utiliser les rails de lucene de manière très efficace.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X