Program guide > Access data with client applications
Data access with indexes (Index API)
Use indexing as an alternative to key access for data can be more efficient.
Necessary steps
- Add either static or dynamic index plug-ins to the BackingMap.
- Obtain application index proxy object by issuing the getIndex method of ObjectMap.
- Cast the index proxy object to an appropriate application index interface, such as MapIndex, MapRangeIndex, or a customized index interface.
- Use the methods defined in the application index interface to find cached objects.
The HashIndex class is the built-in index plug-in implementation that can support both of the built-in application index interfaces: MapIndex and MapRangeIndex. You also can create the own indexes. You can add HashIndex as either a static or dynamic index into the BackingMap, obtain either MapIndex or MapRangeIndex index proxy object, and use the index proxy object to find cached objects.
In a distributed environment, if the index object is obtained from a client ObjectGrid, it will have type client index object and all index operations will run in a remote server ObjectGrid. If the map is partitioned, the index operation will run on each partition remotely and results from each partition will be merged before returning them to the application. The performance will be determined by the number of partitions and the size of the result returned by each partition. Poor performance may occur if both factors are high.
For information about configuring the HashIndex, refer to Configure the HashIndex.
To write the own index plug-in, see Plug-ins for custom indexing of cache objects.
For information regarding indexing, see Indexing and Use a composite index.
Add static index plug-ins
Use two approaches to add static index plug-ins into the BackingMap configuration: XML configuration and programmatic configuration. The following example illustrates the XML configuration approach.
Add static index plug-ins: XML configuration approach
<backingMapPluginCollection id="person"> <bean id="MapIndexplugin" className="com.ibm.websphere.objectgrid.plugins.index.HashIndex"> <property name="Name" type="java.lang.String" value="CODE" description="index name" /> <property name="RangeIndex" type="boolean" value="true" description="true for MapRangeIndex" /> <property name="AttributeName" type="java.lang.String" value="employeeCode" description="attribute name" /> </bean> </backingMapPluginCollection>
In this XML configuration example, the built-in HashIndex class is used as the index plug-in. The HashIndex supports properties that users can configure, such as Name, RangeIndex, and AttributeName in the previous example.
- The Name property is configured as “CODE”, a string identifying this index plug-in. The Name property value must be unique within the scope of the BackingMap, and can be used to retrieve the index object by name from the ObjectMap instance for the BackingMap.
- The RangeIndex property is configured as “true”, which means the application can cast the retrieved index object to the MapRangeIndex interface. If the RangeIndex property is configured as “false”, the application can only cast the retrieved index object to the MapIndex interface. A MapRangeIndex supports functions to find data using range functions such as greater than, less than, or both, while a MapIndex only supports equals functions. If the index will be used by query, the RangeIndex property must be configured to “true” on single-attribute indexes. For a relationship index and composite index, the RangeIndex property must be configured to “false”.
- The AttributeName property is configured as “employeeCode”, which means the employeeCode attribute of the cached object is used to build a single-attribute index. If an application needs to search for cached objects with multiple attributes, the AttributeName property can be set to a comma-delimited list of attributes, yielding a composite index.
See Configure the HashIndex for more information.
The BackingMap interface has two methods that you can use to add static index plug-ins: addMapIndexplugin and setMapIndexplugins. For more information, see BackMap API.
The following code example illustrates the programmatic configuration approach:
Add static index plugins: programmatic configuration approach
import com.ibm.websphere.objectgrid.ObjectGridManagerFactory; import com.ibm.websphere.objectgrid.ObjectGridManager; import com.ibm.websphere.objectgrid.ObjectGrid; import com.ibm.websphere.objectgrid.BackingMap; ObjectGridManager ogManager = ObjectGridManagerFactory.getObjectGridManager(); ObjectGrid ivObjectGrid = ogManager.createObjectGrid( "grid" ); BackingMap personBackingMap = ivObjectGrid.getMap("person"); // use the builtin HashIndex class as the index plugin class. HashIndex mapIndexplugin = new HashIndex(); mapIndexplugin.setName("CODE"); mapIndexplugin.setAttributeName("EmployeeCode"); mapIndexplugin.setRangeIndex(true); personBackingMap.addMapIndexplugin(mapIndexplugin);
Use static indexes
After a static index plug-in is added to a BackingMap configuration and the containing ObjectGrid instance is initialized, applications can retrieve the index object by name from the ObjectMap instance for the BackingMap. Cast the index object to the application index interface. Operations that the application index interface supports can now run.
The following code example illustrates how to retrieve and use static indexes.
Use static indexes example
Session session = ivObjectGrid.getSession(); ObjectMap map = session.getMap("person "); MapRangeIndex codeIndex = (MapRangeIndex) m.getIndex("CODE"); Iterator iter = codeIndex.findLessEqual(new Integer(15)); while (iter.hasNext()) { Object key = iter.next(); Object value = map.get(key); }
Add, removing, and using dynamic indexes
You can create and remove dynamic indexes from a BackingMap instance programmatically at any time. A dynamic index differs from a static index in that the dynamic index can be created even after the containing ObjectGrid instance is initialized. Unlike static indexing, the dynamic indexing is an asynchronous process and needs to be in ready state before you use it. This method uses the same approach for retrieving and using the dynamic indexes as static indexes. You can remove a dynamic index if it is no longer needed. The BackingMap interface has methods to create and remove dynamic indexes.
See the BackingMap API for more information about the createDynamicIndex and removeDynamicIndex methods.
Use dynamic indexes example
import com.ibm.websphere.objectgrid.ObjectGridManagerFactory; import com.ibm.websphere.objectgrid.ObjectGridManager; import com.ibm.websphere.objectgrid.ObjectGrid; import com.ibm.websphere.objectgrid.BackingMap; ObjectGridManager ogManager = ObjectGridManagerFactory.getObjectGridManager(); ObjectGrid og = ogManager.createObjectGrid("grid"); BackingMap bm = og.getMap("person"); og.initialize(); // create index after ObjectGrid initialization without DynamicIndexCallback. bm.createDynamicIndex("CODE", true, "employeeCode", null); try { // If not using DynamicIndexCallback, need to wait for the Index to be ready. // The waiting time depends on the current size of the map Thread.sleep(3000); } catch (Throwable t) { // ... } // When the index is ready, applications can try to get application index // interface instance. // Applications have to find a way to ensure that the index is ready to use, // if not using DynamicIndexCallback interface. // The following example demonstrates the way to wait for the index to be ready // Consider the size of the map in the total waiting time. Session session = og.getSession(); ObjectMap m = session.getMap("person"); MapRangeIndex codeIndex = null; int counter = 0; int maxCounter = 10; boolean ready = false; while (!ready && counter < maxCounter) { try { counter++; codeIndex = (MapRangeIndex) m.getIndex("CODE"); ready = true; } catch (IndexNotReadyException e) { // implies index is not ready, ... System.out.println("Index is not ready. continue to wait."); try { Thread.sleep(3000); } catch (Throwable tt) { // ... } } catch (Throwable t) { // unexpected exception t.printStackTrace(); } } if (!ready) { System.out.println("Index is not ready. Need to handle this situation."); } // Use the index to peform queries // Refer to the MapIndex or MapRangeIndex interface for supported operations. // The object attribute on which the index is created is the EmployeeCode. // Assume that the EmployeeCode attribute is Integer type: the // parameter that is passed into index operations has this data type. Iterator iter = codeIndex.findLessEqual(new Integer(15)); // remove the dynamic index when no longer needed bm.removeDynamicIndex("CODE");
DynamicIndexCallback interface
The DynamicIndexCallback interface is designed for applications that want to get notifications at the indexing events of ready, error, or destroy. The DynamicIndexCallback is an optional parameter for the createDynamicIndex method of the BackingMap. With a registered DynamicIndexCallback instance, applications can run business logic upon receiving notification of an indexing event. For example, the ready event means that the index is ready for use. When a notification for this event is received, an application can try to retrieve and use the application index interface instance. See the DynamicIndexCallback API for more information.
The following code example illustrates the use of the DynamicIndexCallback interface:
Use DynamicIndexCallback interface
BackMap personBackingMap = ivObjectGrid.getMap("person"); DynamicIndexCallback callback = new DynamicIndexCallbackImpl(); personBackingMap.createDynamicIndex("CODE", true, "employeeCode", callback); class DynamicIndexCallbackImpl implements DynamicIndexCallback { public DynamicIndexCallbackImpl() { } public void ready(String indexName) { System.out.println("DynamicIndexCallbackImpl.ready() -> indexName = " + indexName); // Simulate what an application would do when notified that the index is ready. // Normally, the application would wait until the ready state is reached and then proceed // with any index usage logic. if("CODE".equals(indexName)) { ObjectGridManager ogManager = ObjectGridManagerFactory.getObjectGridManager(); ObjectGrid og = ogManager.createObjectGrid( "grid" ); Session session = og.getSession(); ObjectMap map = session.getMap("person"); MapIndex codeIndex = (MapIndex) map.getIndex("CODE"); Iterator iter = codeIndex.findAll(codeValue); } } public void error(String indexName, Throwable t) { System.out.println("DynamicIndexCallbackImpl.error() -> indexName = " + indexName); t.printStackTrace(); } public void destroy(String indexName) { System.out.println("DynamicIndexCallbackImpl.destroy() -> indexName = " + indexName); } }
- Indexing
Use the MapIndexPlugin to build an index or several indexes on a BackingMap to support non-key data access.
- Plug-ins for custom indexing of cache objects
With a MapIndexPlugin plug-in, or index, you can write custom indexing strategies that are beyond the built-in indexes that eXtreme Scale provides.
- Plug-ins for indexing data
The built-in HashIndex, or com.ibm.websphere.objectgrid.plugins.index.HashIndex class) is a MapIndexPlugin plug-in that you can add into BackingMap to build static or dynamic indexes. It supports both the MapIndex and MapRangeIndex interfaces. Defining and using indexes properly can significantly improve query performance.
Parent topic:
Access data with client applications
Related concepts
Interacting with an ObjectGrid using ObjectGridManager
Access data in WebSphere eXtreme Scale
Use Sessions to access data in the grid
Cache objects with no relationships involved (ObjectMap API)
Cache objects and their relationships (EntityManager API)
Retrive entities and objects (Query API)
Configure clients with WebSphere eXtreme Scale
Query optimization using indexes
Related tasks
Related reference
Connect to a distributed ObjectGrid