You are currently browsing legacy 3.0 version of documentation. Click here to switch to the newest 4.2 version.

We can help you with migration to the latest RavenDB

Contact Us Now
see on GitHub

Indexing polymorphic data

By default, RavenDB indexes operate only on a specific entity type, or a Collection, and it ignores the inheritance hierarchy.

For example, let's assume that we have the following inheritance hierarchy:

Figure 1: Polymorphic indexes

If we saved a Cat, it would have an Entity-Name of "Cats" and if we saved a Dog, it would have an Entity-Name of "Dogs".

If we wanted to index cats by name, we would write:

from cat in docs.Cats
select new { cat.Name }

And for dogs:

from dog in docs.Dogs
select new { dog.Name }

Although it works, each index would only give us results for the animal it has been defined on. But what if we wanted to query across all animals?

Multi-map indexes

The easiest way to do this is by writing a multi-map index like this one:

public class Animals_ByName : AbstractMultiMapIndexCreationTask
{
	public Animals_ByName()
	{
		AddMap<Cat>(cats => from c in cats select new { c.Name });

		AddMap<Dog>(dogs => from d in dogs select new { d.Name });
	}
}

And query it like this:

List<object> results = session
	.Advanced
	.DocumentQuery<object, Animals_ByName>()
	.WhereEquals("Name", "Mitzy")
	.ToList();

You can also use the LINQ provider if your objects implement an interface, IAnimal for instance:

IList<IAnimal> results = session
	.Query<IAnimal, Animals_ByName>()
	.Where(x => x.Name == "Mitzy")
	.ToList();

Other ways

Another option would be to modify the way we generate the Entity-Name for subclasses of Animal, like this:

DocumentStore store = new DocumentStore()
{
	Conventions =
	{
		FindTypeTagName = type =>
		{
			if (typeof(Animal).IsAssignableFrom(type))
				return "Animals";
			return DocumentConvention.DefaultTypeTagName(type);
		}
	}
};

Using this method, we can now index on all animals using:

from animal in docs.Animals
select new { animal.Name }

But what happens when you don't want to modify the entity name of an entity itself?

You can create a polymorphic index using:

from animal in docs.WhereEntityIs("Cats", "Dogs")
select new { animal.Name }

It will generate an index that matches both Cats and Dogs.