# Indexes and Cursors in C#

> As explained in the Indexes and Cursors page, eXtremeDB supports a variety of index types. The following sections give implementation details for C# 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.

> A `BTree` index can be specified in the database class definition by specifying the `[Indexable]` field attribute 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 )

> 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 attribute, which has the same optional modifiers. For example:

>         [Persistent]
>         [Index("byDept_EmployeeName", Keys = new string[] { "dept_no", "name" }, Unique = false)]
>         class Employee
>         {
>             [Indexable(Type = Database.IndexType.BTree, Unique = true)]
>             public String  name;
>             public int  dept_no;
>         }

> Note that the `[Index]` class attribute 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.

> ### 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, "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, "byDept_EmployeeName");
>         if (cursor.Search(Operation.GreaterOrEquals, emp1.dept_no, "") )
>         {
>             foreach (Employee e in 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");
>         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");
>         if (cursor.Search(Operation.GreaterOrEquals, "360") )
>         {
>             foreach (AreaCode a in 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 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, `rtree` searches are performed using the Cursor method `Search()` with one of the four types of search operations: `Equals, Contains, Overlaps` or `Neighborhood`. Please refer to the Searches page for implementation details.

> ## 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()` 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
>             public int iIdx;

>             [Indexable(Type=Database.IndexType.Hashtable, Unique=false, InitSize=10000)] // Declare non-unique hash index
>             public 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)]` attribute. For example:

>         [Persistent(List=true)]
>         class Rect
>         {
>             [Dimension(4)]
>             [Indexable(Type=Database.IndexType.RTree)] // Declare rtree index on "square" field
>             public short[] square;
>         }