Created
May 16, 2016 22:05
-
-
Save hyrmn/4aa61a6cdc0ab64926ac5901c1d52ca0 to your computer and use it in GitHub Desktop.
Querying child collections by id in RavenDB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Foo | |
{ | |
public string Id { get; set; } | |
public string Name { get; set; } | |
public Bar[] Bars { get; set; } | |
} | |
public class Bar | |
{ | |
public string Id { get; set; } | |
public string Name { get; set; } | |
} | |
public class FooIndex : AbstractIndexCreationTask<Foo> | |
{ | |
public FooIndex() | |
{ | |
Map = docs => from doc in docs | |
select new | |
{ | |
doc.Name, | |
Bars_Id = doc.Bars.Select(bar => bar.Id) | |
}; | |
Store(x => x.Bars.Select(b => b.Id), FieldStorage.Yes); | |
Index(x => x.Bars.Select(b => b.Id), FieldIndexing.Analyzed); | |
} | |
} | |
public class FooChildIdsNotAnalyzedIndex : AbstractIndexCreationTask<Foo> | |
{ | |
public FooChildIdsNotAnalyzedIndex() | |
{ | |
Map = docs => from doc in docs | |
select new | |
{ | |
doc.Name, | |
BarIds = doc.Bars.Select(bar => bar.Id) | |
}; | |
Store(x => x.Bars.Select(b => b.Id), FieldStorage.Yes); | |
Index(x => x.Bars.Select(b => b.Id), FieldIndexing.NotAnalyzed); | |
} | |
} | |
public class NoStaleQueriesAllowed : IDocumentQueryListener | |
{ | |
public void BeforeQueryExecuted(IDocumentQueryCustomization queryCustomization) | |
{ | |
queryCustomization.WaitForNonStaleResults(); | |
} | |
} | |
public class ChildCollectionQueryTests | |
{ | |
private readonly EmbeddableDocumentStore documentStore; | |
public ChildCollectionQueryTests() | |
{ | |
documentStore = new EmbeddableDocumentStore | |
{ | |
Configuration = | |
{ | |
RunInUnreliableYetFastModeThatIsNotSuitableForProduction = true, | |
RunInMemory = true | |
} | |
}; | |
documentStore.ConfigureSerializers(); | |
documentStore.RegisterListener(new NoStaleQueriesAllowed()); | |
documentStore.Initialize(); | |
} | |
public void searching_by_child_id_on_not_analyzed_errors() | |
{ | |
new FooChildIdsNotAnalyzedIndex().Execute(documentStore.DatabaseCommands, documentStore.Conventions); | |
using (var session = documentStore.OpenSession()) | |
{ | |
var fooOne = new Foo {Id = "foos/1", Name = "First Foo", Bars = new[] {new Bar {Id = "Bars/1", Name = "Bar"}}}; | |
var fooTwo = new Foo {Id = "foos/2", Name = "Foo the Greater"}; | |
session.Store(fooOne); | |
session.Store(fooTwo); | |
session.SaveChanges(); | |
var fooSearch = session.Query<Foo, FooChildIdsNotAnalyzedIndex>().Where(x => x.Bars.Any(b => b.Id == "Bars/1")); | |
Should.Throw<ArgumentException>(() => fooSearch.ToList()); | |
} | |
} | |
public void can_search_child_collection_by_id_if_analyzed() | |
{ | |
new FooIndex().Execute(documentStore.DatabaseCommands, documentStore.Conventions); | |
using (var session = documentStore.OpenSession()) | |
{ | |
var fooOne = new Foo {Id = "foos/1", Name = "First Foo", Bars = new[] {new Bar {Id = "Bars/1", Name = "Bar"}}}; | |
var fooTwo = new Foo {Id = "foos/2", Name = "Foo the Greater"}; | |
session.Store(fooOne); | |
session.Store(fooTwo); | |
session.SaveChanges(); | |
var fooSearch = session.Query<Foo, FooIndex>().Where(x => x.Bars.Any(b => b.Id == "Bars/1")); | |
var foos = fooSearch.ToList(); | |
foos.Count.ShouldBe(1); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note the failure here is that, while Raven's recommendation is to store Ids as NotAnalyzed, you must store them Analyzed if you're storing a collection... which makes sense. an id (or any field) in a child collection is just a piece of data as far as Raven cares.
Also, note the mapped field must be called Bars_Id. This is due to the convention-based naming Raven uses