As explained in the Indexes and Cursors page, eXtremeDB supports a variety of index types. The following sections give implementation details for Java APIs used to manage each of these index types.
B-Tree Indexes
As explained in the B-Tree Indexes page,
BTreeindexes can be used for ordered (sorted) retrieval and range retrieval.There are several ways to specify a BTree index.
First, a
BTreeindex can be specified in the database class definition by specifying the@Indexablefield annotation, which has optional modifiers:
Descending- Sort in reverse order (default is ascending order ifDescendingis not specified).Thick- Optimized for a large number of duplicates.Unique-true: no duplicate values allowed, orfalse: allow duplicate values (default ifUniqueis not specified).(The index will get the same name as the field.)
For example:
@Persistent class Obj { @Indexable(type=Database.IndexType.BTree, unique=true) public int value; }An alternative method to create a
BTreeindex is to specify the@Indexclass annotation, which has the same optional modifiers. For example:@Persistent @Index("byDept_EmployeeName", keys={@Key("dept_no"), @Key("name")}, unique=true) class Employee { @Indexable(type = Database.IndexType.BTree, unique = true) public String name; public int dept_no; }Note that the
@Indexclass annotation is typically used for multi-field or compound indexes (as in the above case), but it can also be used for a single-field index.Finally, multiple indexes (including compound) can be declared at once inside the
@Indexes(...)annotation, for example:@Indexes({ @Index(name="byName", keys={@Key("lastName"), @Key("firstName")}, unique=true, initSize=100), @Index(name="byAddress", keys={@Key("address.country"), @Key("address.city"), @Key("address.street")}, unique=false, initSize=100), @Index(name="bySalary", keys={@Key(value="salary", descending=true)}, initSize=100) }) class Employee { String firstName; String lastName; Address address; long salary; ... }Cursors and Searches
To initiate an "exact match" search for
Unique BTreeindexes (which enforce the uniqueness constraint), the Cursor methodfind()is used. For example:Connection con = new Connection(db); con.startTransaction(Database.TransactionType.ReadWrite); Cursor<Employee> cursor = new Cursor<Employee>(con, Employee.class, "name"); Employee emp = cursor.find("William"); con.commitTransaction();To initiate a search for non-Unique
BTreeindexes, the Cursor methodsearch()is used. For example:Connection con = new Connection(db); con.startTransaction(Database.TransactionType.ReadWrite); Cursor<Employee> cursor = new Cursor<Employee>(con, Employee.class, "byDept_EmployeeName"); if (cursor.search(Operation.GreaterOrEquals, emp1.dept_no, "")) { for (Employee e : cursor) { // Process Employee object } } con.commitTransaction();The Cursor methods
moveFirst(),moveLast(),moveNext(), andmovePrev()are used to navigate through the result set of a search operation. Please refer to the Searches page for further implementation details.Patricia Trie Indexes
As explained in the Patricia Indexes page, the eXtremeDB
Patriciaindex is particularly useful for network and telecommunications applications. APatriciaindex can be declared overStringfields by specifying the@Indexablefield attribute. It can also be declaredUnique; in the absence of theUniquekeyword, it defaults to allowing duplicates. Unlike other eXtremeDB indexes, thePatriciaindex cannot be compound; it is always declared for a single field.For example:
@Persistent class AreaCode { @Indexable(type=Database.IndexType.Patricia) // Declare patricia index by "areaCode" field public String areaCode; public int value; }Cursors and Searches
To initiate an "exact match" search for
Unique Patriciaindexes (which enforce the uniqueness constraint), the Cursor methodfind()is used. For example:Connection con = new Connection(db); con.startTransaction(Database.TransactionType.ReadWrite); Cursor<AreaCode> cursor = new Cursor<AreaCode>(con, AreaCode.class, "areaCode"); AreaCode ac = cursor.find("360"); con.commitTransaction();To initiate a search for non-Unique
Patriciaindexes, the Cursor methodsearch()is used. For example:Connection con = new Connection(db); con.startTransaction(Database.TransactionType.ReadWrite); Cursor<AreaCode> cursor = new Cursor<AreaCode>(con, AreaCode.class, "areaCode"); if (cursor.search(Operation.GreaterOrEquals, "360")) { for (AreaCode a : cursor) { // Process AreaCode object } } con.commitTransaction();The Cursor methods
moveFirst(),moveLast(),moveNext(), andmovePrev()are used to navigate through the result set of a search operation. Please refer to the Searches page for further implementation details.RTree Indexes
As explained in the R-Tree Index page, an
RTreeindex is commonly used to speed up spatial searches. AnRTreeindex is typically defined for an array field containing the number of coordinates required to describe a "rectangle". For example:@Persistent(list=true) class Rect { @Dimension(4) @Indexable(type=Database.IndexType.RTree) // Declare rtree index on "square" field public short[] square; }Cursors and Searches
As explained in the R-Tree Index page,
rtreesearches are performed using the Cursor methodsearch()with one of the four types of search operations:Equals,Contains,Overlaps, orNeighborhood. Please refer to the Searches page for implementation details.KDTree Indexes
KDTree indexes are not supported in the Java API.
Trigram Indexes
As explained in the Trigram Index page,
Trigramindexes are ideal for text searches when the exact spelling of the target object is not precisely known. ATrigramindex is typically defined for aStringfield. For example:@Persistent(list=true) class Obj { @Indexable(type=Database.IndexType.Trigram) public String str; }Cursors and Searches
As explained in the Trigram Index page,
Trigramsearches are performed using the Cursor methodsearch()with the search operation typeContains. Please refer to the Searches page for implementation details.HNSW Indexes
As explained in the HNSW Indexes page,
HNSWindexes are ideal for fast approximate nearest neighbor search in high-dimensional spaces. The Java API defines HNSW and Vamana indexes through annotations:@Persistent class AnnEmbedding { static final int DIM = 3; static final int INDEX_M = 16; @Indexable(type=Database.IndexType.BTree, unique=true) public int pk; @Dimension(DIM) @Indexable(type=Database.IndexType.HNSW, initSize=INDEX_M) public float[] coord; }Options are set before opening or building the database:
Database db = new Database(); db.setRuntimeOption(Database.RT_OPTION_HNSW_M, 16); db.setRuntimeOption(Database.RT_OPTION_HNSW_DIST_FUNC, Database.DIST_L2); db.setRuntimeOption(Database.RT_OPTION_HNSW_EF_CONSTRUCTION, 64); db.setRuntimeOption(Database.RT_OPTION_HNSW_EF_SEARCH, 128); db.setRuntimeOption(Database.RT_OPTION_VAMANA_ALPHA, 0);For Vamana indexes, specify a positive
VAMANA_ALPHAvalue and optionally choose a build method:db.setRuntimeOption(Database.RT_OPTION_VAMANA_ALPHA, 120); db.setRuntimeOption(Database.RT_OPTION_VAMANA_BUILD_METHOD, Database.VAMANA_BUILD_INCREMENTAL);Java applications can also use SQL DDL and SQL
NEARqueries through the Java SQL API or JDBC instead of static annotations. See the SQL SELECT page for details on theNEARoperator.Cursors and Searches
HNSW and Vamana searches are performed using the Cursor method
search()with operationCursor.Operation.Neighbourhoodand the pattern vector as the search key. Please refer to the Searches page for implementation details.Hash Indexes
As explained in the Hash and Autoid Indexes page,
HashTableindexes are ideal for quick lookup of individual database objects.HashTableindexes can be declaredunique=trueorunique=false, and they require an extra parameter,initSize. It is an integer number that the runtime uses to allocate the initial hash table for the index. It must be specified but is not required to be exact. For example:@Persistent class Record { @Indexable(type=Database.IndexType.Hashtable, unique=true, initSize=10000) // Declare unique hash index int iIdx; @Indexable(type=Database.IndexType.Hashtable, unique=false, initSize=10000) // Declare non-unique hash index int iSeries; }Note that the
initSize=10000specification for indexesiIdxandiSeriescauses the runtime to allocate initial hash tables with10000“buckets”.Cursors and Searches
As explained in the Hash and Autoid Indexes page,
HashTablesearches are performed using the Cursor methodsfind()orsearch()depending on whether theuniquedeclaration istrueorfalse. Please refer to the Searches page for implementation details.List Indexes
The
Listindex, like a non-uniqueHashTable, allows navigation in sequential order (first to last, or last to first) over the unordered list of objects of a class. To create aListindex on a class, use the@Persistent(list=true)annotation. For example:@Persistent(list=true) class Rect { @Dimension(4) @Indexable(type=Database.IndexType.RTree) // Declare rtree index on "square" field public short[] square; }