Finding objects which contains at least all elements from subset using RavenDB and LINQ

.net, c#, linq, ravendb

Solution

Jarek, what you want to do is:

var q = session.Query<Question>();
foreach(var tag in tags)
{
    var currentTag = tag;
    q = q.Where(x=>x.Tags.Any(xTag=>xTag == currentTag));
}

This will give you all the questions that have at least all those tags.

Problem

I have simple type `Question`: ``` public class Question { public Question(string id) { Id = id; Tags = new List<string>(); } public string Id { get; private set; } public IList<string> Tags { get; set; } } ``` I have defined sample collection of such questions: ``` var q1 = new Question("q1") { Tags = new List<string>() {"aa", "bb"} }; var q2 = new Question("q2") { Tags = new List<string>() {"aa"} }; var q3 = new Question("q3") { Tags = new List<string>() {"aa", "bb", "cc"} }; var q4 = new Question("q4"); var questions = new List<Question>() {q1, q2, q3, q4}; ``` Now I need to find all questions, which contains at least all tags, from given subset. Subset is defined below: ``` string[] tags = new[] {"aa", "bb"}; ``` The query which I use to get desired result is: ``` var result = questions.Where(x => !tags.Except(x.Tags).Any()).ToList(); ``` Result is a list of 2 questions: q1 and q3, which works properly while I'm using linq-to-objects. Unfortunately, while I'm trying to query such questions, which are now persisted in RavenDB, I get an exception: ``` var result = DocumentSession.Query<Question>() .Where(x => !tags.Except(x.Tags).Any()).ToList(); ``` results in: ``` System.InvalidOperationException: Cannot understand how to translate value(Core.Commands.GetQuestions+<>c__DisplayClass0).tags.Except(x.Tags) at Raven.Client.Linq.RavenQueryProviderProcessor`1.GetPath(Expression expression, String& path, Type& memberType, Boolean& isNestedPath) at Raven.Client.Linq.DynamicQueryProviderProcessor`1.GetMember(Expression expression) at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitAny(MethodCallExpression expression) at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitEnumerableMethodCall(MethodCallExpression expression) at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitMethodCall(MethodCallExpression expression) at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitExpression(Expression expression) at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitExpression(Expression expression) at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitQueryableMethodCall(MethodCallExpression expression) at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitMethodCall(MethodCallExpression expression) at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitExpression(Expression expression) at Raven.Client.Linq.RavenQueryProviderProcessor`1.GetLuceneQueryFor(Expression expression) at Raven.Client.Linq.RavenQueryProviderProcessor`1.Execute(Expression expression) at Raven.Client.Linq.DynamicRavenQueryProvider`1.Execute(Expression expression) at Raven.Client.Linq.DynamicRavenQueryProvider`1.System.Linq.IQueryProvider.Execute(Expression expression) at Raven.Client.Linq.RavenQueryInspector`1.GetEnumerator() at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) ... ``` How to perform what I want using RavenDB ?

Original source