NEW Feature - Intersection queries

349 views
Skip to first unread message

Matt Warren

unread,
Mar 23, 2012, 5:44:15 AM3/23/12
to rav...@googlegroups.com
With more than I little help from Oren/Itamar, there's now a new feature available in RavenDB.

The issue is that Lucene indexes are essentially "flat", but Raven can obviously store hierachial data, i.e. a POCO with an embedded list of other POCO's (for instance). 

So If you have the following POCO:

public class TShirt
{
public String Id { get; set; }
public String Name { get; set; }
public int BarcodeNumber { get; set; }
public List<TShirtType> Types { get; set; }
}

public class TShirtType
{
public String Colour { get; set; }
public String Size { get; set; }
}

Up to now you've not been able to say, "Give me all the TShirts that have (Colour = Blue, Size = Small) AND (Colour = Gray, Size = Large)".
Note: you could do that search if you put an "OR" in there, but not "AND".

But now you can do this type of query (and others) using the Intersect() LINQ extension method, like so (note: it supports ordering & paging):
var shirts = session.Query<TShirt>("TShirtNested")
.OrderBy(x=>x.BarcodeNumber)
.Where(x => x.Name == "Wolf")
.Intersect()
.Where(x => x.Types.Any(t => t.Colour == "Blue" && t.Size == "Small"))
.Intersect()
.Where(x => x.Types.Any(t => t.Colour == "Gray" && t.Size == "Large"))
.ToList();

Querying against an index that looks like this:
store.DatabaseCommands.PutIndex("TShirtNested",
new IndexDefinition
{
Map =
@"from s in docs.TShirts
from t in s.Types
select new { s.Name, Types_Colour = t.Colour, Types_Size = t.Size, s.BarcodeNumber }",
SortOptions = new Dictionary<String, SortOptions> {{"BarcodeNumber", SortOptions.Int}}
});

I'll post some better documentation early next week and I'll try and put together a couple more code samples that show the functionality, but in the meantime you can take a look at the existing unit tests

Any questions, comments?

Matt Johnson

unread,
Mar 23, 2012, 10:58:56 AM3/23/12
to ravendb
I'm glad the feature is there, but it seems a bit unintuitive to need
the Intersect() method. Can you explain a bit more why it is
required? I would expect that either of the following would work, but
I haven't tried it:

.Where(x => x.Name == "Wolf")
.Where(x => x.Types.Any(t => t.Colour == "Blue" && t.Size ==
"Small"))
.Where(x => x.Types.Any(t => t.Colour == "Gray" && t.Size ==
"Large"))


.Where(x => x.Name == "Wolf"
&& x.Types.Any(t => t.Colour == "Blue" && t.Size == "Small")
&& x.Types.Any(t => t.Colour == "Gray" && t.Size == "Large"))


Thanks,
Matt
> meantime you can take a look at the existing unit tests<https://github.com/ayende/ravendb/blob/master/Raven.Tests/Queries/Int...>
>
> Any questions, comments?
>
>

Oren Eini (Ayende Rahien)

unread,
Mar 23, 2012, 11:00:14 AM3/23/12
to rav...@googlegroups.com
Matt,
that is because there isn't a single index entry that matches all three queries.

Matt Johnson

unread,
Mar 23, 2012, 11:32:16 AM3/23/12
to ravendb
Got it. So basically the way to think about it is that you can have
multiple indexes participating in the same query plan? That's pretty
cool!

-Matt

On Mar 23, 8:00 am, "Oren Eini (Ayende Rahien)" <aye...@ayende.com>
wrote:

Oren Eini (Ayende Rahien)

unread,
Mar 23, 2012, 11:35:31 AM3/23/12
to rav...@googlegroups.com
Yes, that is the idea, but that applies for a single index only.
Reply all
Reply to author
Forward
0 new messages