# Indexes and Cursors in Java

> 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, `BTree` indexes can be used for ordered (sorted) retrieval, range retrieval.

> There are several ways to specify a BTree index.

> First, a `BTree` index can be specified in the database class definition by specifying the `@Indexable` field annotation which has optional modifiers:

> - `Descending` - Sort in reverse order - default is ascending order if `Descending` is not specified
> - `Thick` - Optimized for a large number of duplicates
> - `Unique` - true: no duplicate values allowed, or false: allow duplicate values (default if `Unique` is not specified )

> (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 `BTree` index is to specify the `@Index` class 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 `@Index` class 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 BTree` indexes (which enforce the uniqueness constraint), the Cursor method `find()` 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 `BTree` indexes, the Cursor method `search()` 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()` and `movePrev()` 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 `Patricia` index is particularly useful for network and telecommunications applications. A `Patricia` index can be declared over `String` fields by specifying the `@Indexable` field attribute. It can also be declared `Unique`; in the absence of the `Unique` keyword it defaults to allowing duplicates. Unlike other eXtremeDB indexes, the `Patricia` index 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 Patricia` indexes (which enforce the uniqueness constraint), the Cursor method `find()` 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 `Patricia` indexes, the Cursor method `search()` 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()` and `movePrev()` 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 `RTree` index is commonly used to speed spatial searches. An `RTree` index is typically defined for a 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, `rtree` searches are performed using the Cursor method `Search()` is used with one of the four types of search operations: `Equals, Contains, Overlaps` or `Neighborhood`. 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, `Trigram` indexes are ideal for text searches when the exact spelling of the target object is not precisely known.. A `Trigram` index is typically defined for a `String` field. 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, `Trigram` searches are performed using the Cursor method `search()` is used with search operation type: `Contains`. Please refer to the Searches page for implementation details.

> ## Hash Indexes

> As explained in the Hash and Autoid Indexes page, `HashTable` indexes are ideal for quick lookup of individual database objects. `HashTable` indexes can be declared `unique=true` or `unique=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 `[10000]` specification for indexes `iIdx` and `iSeries` cause the runtime to allocate initial hash tables with `10000` “buckets”.

> ### Cursors and Searches

> As explained in the Hash and Autoid Indexes page, `HashTable` searches are performed using the Cursor methods `find()` or `search()` depending on whether the `unique` declaration is `true` or `false`. Please refer to the Searches page for implementation details.

> ## List Indexes

> The `List` index, like a non-unique `HashTable`, allows navigation in sequential order (first to last, or last to first) over the unordered list of objects of a class. To create a `List` index 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;
>         }