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;