[Java programming language only]

Accessing data with indexes (Index API)

Use indexing for more efficient data access.

About this task

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 your own indexes. You can add HashIndex as either a static or dynamic index into the backing map, obtain either MapIndex or MapRangeIndex index proxy object, and use the index proxy object to find cached objects.

If you want to iterate through the keys in a local map, you can use the default index. This index does not require any configuration, but it must be used against the shard, using an agent or an ObjectGrid instance retrieved from the ShardEvents.shardActivated(ObjectGrid shard) method.

Note: In a distributed environment, if the index object is obtained from a client ObjectGrid, the index has a type client index object and all index operations run in a remote server ObjectGrid. If the map is partitioned, the index operations run on each partition remotely. The results from each partition are merged before returning the results to the application. The performance is determined by the number of partitions and the size of the result returned by each partition. Poor performance might occur if both factors are high.

Procedure

  1. If you want to use indexes other than the default local index, add index plug-ins to the backing map.
    • XML configuration:
      <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 class 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 is 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.
    • Programmatic configuration:

      The BackingMap interface has two methods that you can use to add static index plug-ins: addMapIndexplugin and setMapIndexplugins. For more information, see BackingMap API. The following example creates the same configuration as the XML configuration 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 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);
  2. Access map keys and values with indexes.
    • Local index:
      To iterate through the keys and values in a local map, you can use the default index. The default index only works against the shard, using an agent or using the ObjectGrid instance retrieved from the ShardEvents.shardActivated(ObjectGrid shard) method. See the following example:
      MapIndex keyIndex = (MapIndex)
      objMap.getIndex(MapIndexPlugin.SYSTEM_KEY_INDEX_NAME);
      Iterator keyIterator = keyIndex.findAll();
    • 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.

      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);
      }
      // Close the session (optional in Version 7.1.1 and later) for improved performance
      session.close();
    • 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, which requires the dynamic index 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.

      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");
      	// Close the session (optional in Version 7.1.1 and later) for improved performance
      	session.close();

What to do next

You can use the DynamicIndexCallback interface to get notifications at the indexing events. See DynamicIndexCallback interface for more information.