Query an array property for ALL matches

860 views
Skip to first unread message

jalchr

unread,
Aug 14, 2011, 6:01:58 PM8/14/11
to rav...@googlegroups.com

So I have 2 documents:
{
 Id : "Groups\234"
 Name : "Group1",
 Colors: ["Green", "White", "Red"]
},
{
 Id : "Groups\654"
 Name : "Group2",
 Colors: ["Black", "White", "Red", "Blue"]
},

I'm trying to query for documents which contain "White" and "Red"

using (var s = store.OpenSession())
{
   var query = new [] {"White", "Red"}; 
    var results = s.Query<Group>()
                          .Where(x => x.Colors.All(y => y.In( query))
                          .ToArray();
 Assert.True(results.Length == 2);
}
Question: Is there a better way to do such query ?

Unfortunately ... this fails with:

System.NotSupportedException : Method not supported: All
at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitEnumerableMethodCall(MethodCallExpression expression) in RavenQueryProviderProcessor.cs: line 594
at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitMethodCall(MethodCallExpression expression) in RavenQueryProviderProcessor.cs: line 540
at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitExpression(Expression expression) in RavenQueryProviderProcessor.cs: line 114
at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitExpression(Expression expression) in RavenQueryProviderProcessor.cs: line 118
at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitQueryableMethodCall(MethodCallExpression expression) in RavenQueryProviderProcessor.cs: line 645
at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitMethodCall(MethodCallExpression expression) in RavenQueryProviderProcessor.cs: line 528
at Raven.Client.Linq.RavenQueryProviderProcessor`1.VisitExpression(Expression expression) in RavenQueryProviderProcessor.cs: line 114
at Raven.Client.Linq.RavenQueryProviderProcessor`1.GetLuceneQueryFor(Expression expression) in RavenQueryProviderProcessor.cs: line 987
at Raven.Client.Linq.RavenQueryProviderProcessor`1.Execute(Expression expression) in RavenQueryProviderProcessor.cs: line 1024
at Raven.Client.Linq.DynamicRavenQueryProvider`1.Execute(Expression expression) in DynamicRavenQueryProvider.cs: line 167
at Raven.Client.Linq.DynamicRavenQueryProvider`1.System.Linq.IQueryProvider.Execute(Expression expression) in DynamicRavenQueryProvider.cs: line 230
at Raven.Client.Linq.RavenQueryInspector`1.GetEnumerator() in RavenQueryInspector.cs: line 93
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray(IEnumerable`1 source)




Itamar Syn-Hershko

unread,
Aug 14, 2011, 6:12:53 PM8/14/11
to rav...@googlegroups.com
All is indeed not supported, use double Any instead

    var results = s.Query<Group>()
                          .Where(x => x.Colors.Any(y => y=="Red") && x.Colors.Any(y => y=="White"))
                          .ToArray();

Justin A

unread,
Aug 14, 2011, 10:32:19 PM8/14/11
to ravendb
Heh. I tried to look for the Vote Up image for a split second, before
I realized this isn't SO

*blush* ^ *blush*

jalchr

unread,
Aug 15, 2011, 3:01:59 AM8/15/11
to rav...@googlegroups.com
This returned all documents even the ones that had no "White" nor "Red" 

Do you think supporting "All" will provide a better solution in all cases?


Ayende Rahien

unread,
Aug 15, 2011, 7:52:35 AM8/15/11
to rav...@googlegroups.com
Jaclhr,
Due to the nature of the way that we are generating the dynamic index, it means that there is going to be a different index entry for each color.
I would actually expect that to return nothing, rather than returning all.
To support this you need to define an index using:

from doc in docs.Groups
select new { doc.Colors }

And then query that using:

var q = session.Advanced.LuceneQuery<Group>();

for(int i = 0; i < colors.Length; i++) 
{
   if(i != 0) q.AndAlso();

   q.WhereEquals("Colors", colors[i]);
Message has been deleted

jalchr

unread,
Aug 16, 2011, 5:36:07 AM8/16/11
to rav...@googlegroups.com
That worked ...

I wonder though why a Linq query is producing this:
2011-08-16 12:28:15.3336|DEBUG|Raven.Client.Document.SessionOperations.QueryOperation|Executing query '(Colors ,:Red OR Colors ,:White)' on index 'Groups/Colors' in 'memory #51743704

see the "comma" before the semi-colons

This makes the query processor say:
System.ArgumentException : The field 'Colors,' is not indexed, cannot query on fields that are not indexed

Also, any plans to support "All" or some form of an "And" operation for LINQ ?

Ayende Rahien

unread,
Aug 16, 2011, 7:53:25 AM8/16/11
to rav...@googlegroups.com
What was the Linq query that you used?

The problem of supporting All is that you need a different way to output to the index, so I don't think that it would be easy to do automatically.
Since defining the index manually works fine, I don't think we we do more.

On Tue, Aug 16, 2011 at 5:35 AM, jalchr <jal...@gmail.com> wrote:
That worked ...

I wonder though why a Linq query is producing this:
2011-08-16 12:28:15.3336|DEBUG|Raven.Client.Document.SessionOperations.QueryOperation|Executing query '(Colors ,:Red OR Colors ,:White)' on index 'Groups/Colors' in 'memory #51743704

see the "comma" before the semi-colons

This makes the query processor say:
System.ArgumentException : The field 'Names,' is not indexed, cannot query on fields that are not indexed

jalchr

unread,
Aug 16, 2011, 8:07:49 AM8/16/11
to rav...@googlegroups.com
The linq query was 

using (var s = store.OpenSession())
{
   var query = new [] {"White", "Red"}; 
    var results = s.Query<Group, Group_Colors>()
                          .Where(x => x.Colors.Any(y => y.In( query))
                          .ToArray();
 Assert.True(results.Length == 2);
}

Ayende Rahien

unread,
Aug 16, 2011, 9:20:33 AM8/16/11
to rav...@googlegroups.com
Yes, that is expected, the Linq has no way of knowing how to make it work.
I'll probably be adding something like:

    var results = s.Query<Group, Group_Colors>()
                          .Each(query, (q,v)=> q.Where( x=> Equals(x.Colors, v))
                          .ToArray();

That would give you the ability to do this sort of query directly

jalchr

unread,
Aug 16, 2011, 9:31:16 AM8/16/11
to rav...@googlegroups.com
That would be great 
Reply all
Reply to author
Forward
0 new messages