Multi-Map Indexes
-
Multi-Map indexes allow you to index data from multiple collections, like polymorphic data or any data common to different types.
-
Learn how to index polymorphic data
Learn how to create Multi-Map-Reduce indexes -
In this page:
AddMap
The AddMap
method is used to map fields from a single collection, e.g. Dogs
.
Let's assume that we have Dog
and Cat
classes, both inheriting from the class Animal
:
public static class Dog extends Animal {
}
public static class Cate extends Animal {
}
public abstract static class Animal implements IAnimal {
private String name;
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
}
public interface IAnimal {
String getName();
void setName(String name);
}
Now we can define our index using addMap
and query it as follows:
public static class Animals_ByName extends AbstractMultiMapIndexCreationTask {
public Animals_ByName() {
addMap( "docs.Cats.Select(c => new { " +
" Name = c.Name " +
"})");
addMap( "docs.Dogs.Select(d => new { " +
" Name = d.Name " +
"})");
}
}
public static class Animals_ByName extends AbstractJavaScriptIndexCreationTask {
public Animals_ByName() {
setMaps(Sets.newHashSet(
"map('cats', function (c){ return {name: c.name}})",
"map('dogs', function (d){ return {name: d.name}})"
));
}
}
List<IAnimal> results = session
.query(IAnimal.class, Animals_ByName.class)
.whereEquals("Name", "Mitzy")
.toList();
from index 'Animals/ByName'
where Name = 'Mitzy'
Searching across multiple collections
Another great usage of Multi-Map indexes is smart-search.
To search for products, companies, or employees by their name, you need to define the following index:
public static class Smart_Search extends AbstractMultiMapIndexCreationTask {
public static class Result {
private String id;
private String displayName;
private String collection;
private String content;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getCollection() {
return collection;
}
public void setCollection(String collection) {
this.collection = collection;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
public static class Projection {
private String id;
private String displayName;
private String collection;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getCollection() {
return collection;
}
public void setCollection(String collection) {
this.collection = collection;
}
}
public Smart_Search() {
addMap("docs.Companies.Select(c => new { " +
" Id = Id(c), " +
" Content = new string[] { " +
" c.Name " +
" }, " +
" DisplayName = c.Name, " +
" Collection = this.MetadataFor(c)[\"@collection\"] " +
"})");
addMap("docs.Products.Select(p => new { " +
" Id = Id(p), " +
" Content = new string[] { " +
" p.Name " +
" }, " +
" DisplayName = p.Name, " +
" Collection = this.MetadataFor(p)[\"@collection\"] " +
"})");
addMap("docs.Employees.Select(e => new { " +
" Id = Id(e), " +
" Content = new string[] { " +
" e.FirstName, " +
" e.LastName " +
" }, " +
" DisplayName = (e.FirstName + \" \") + e.LastName, " +
" Collection = this.MetadataFor(e)[\"@collection\"] " +
"})");
// mark 'content' field as analyzed which enables full text search operations
index("Content", FieldIndexing.SEARCH);
// storing fields so when projection (e.g. ProjectInto)
// requests only those fields
// then data will come from index only, not from storage
store("Id", FieldStorage.YES);
store("DisplayName", FieldStorage.YES);
store("Collection", FieldStorage.YES);
}
}
and query it using:
List<Smart_Search.Projection> results = session
.query(Smart_Search.Result.class, Smart_Search.class)
.search("Content", "Lau*")
.selectFields(Smart_Search.Projection.class)
.toList();
for (Smart_Search.Projection result : results) {
System.out.println(result.getCollection() + ": " + result.getDisplayName());
// Companies: Laughing Bacchus Wine Cellars
// Products: Laughing Lumberjack Lager
// Employees: Laura Callahan
}
Remarks
Remember that all map functions must output objects
with an identical shape (the field names have to match).