Managing BDB XML Indices

Adding Indices
Deleting Indices
Replacing Indices
Examining Container Indices
Working with Default Indices
Looking Up Indexed Documents

Indices are set for a container using the container's index specification. You can specify an index either against a specific node and namespace, or you can define default indices that are applied to every node in the container.

You add, delete, and replace indices using the container's index specification. You can also iterate through the specification, so as to examine each of the indices declared for the container. Finally, if you want to retrieve all the indices maintained for a named node, you can use the index specification to find and retrieve them.

An API exists that allows you to retrieve all of the documents or nodes referenced by a given index.

Note

For simple programs, managing the index specification and then setting it to the container (as is illustrated in the following examples) can be tedious. For this reason, BDB XML also provides index management functions directly on the container. Which set of functions your application uses is entirely up to your requirements and personal tastes.

Note

Performing index modifications (for example, adding and replacing indices) on a container that already contains documents can be a very expensive operation — especially if the container holds a large number of documents, or very large documents, or both. This is because indexing a container requires BDB XML to traverse every document in the container.

If you are considering re-indexing a large container, be aware that the operation can take a long time to complete.

Adding Indices

To add an index to a container:

  1. Retrieve the index specification from the container.

  2. Use XmlIndexSpecification.addIndex() to add the index to the container. You must provide to this method the namespace and node name to which the index is applied. You must also identify the indexing strategy.

    If the index already exists for the specified node, then the method silently does nothing.

  3. Set the updated index specification back to the container.

For example:

package dbxml.gettingStarted;

import com.sleepycat.dbxml.XmlContainer;
import com.sleepycat.dbxml.XmlException;
import com.sleepycat.dbxml.XmlIndexSpecification;
import com.sleepycat.dbxml.XmlManager;
import com.sleepycat.dbxml.XmlValue;
...

XmlManager myManager = null;
XmlContainer myContainer = null;

...

try {
    // Get a manager object.
    myManager = new XmlManager();

    // Open a container
    myContainer = 
        myManager.openContainer("exampleData.dbxml");

    // Get the index specification
    XmlIndexSpecification is = myContainer.getIndexSpecification();


    // Add the index. We're indexing "node1" using the default
    // namespace.
    is.addIndex("", "node1", "node-element-presence-none");

    // Save the index specification back to the container.
    myContainer.setIndexSpecification(is);

    is.delete();

} catch (XmlException e) {
    // Error handling goes here.
} finally {
    try {
        if (myContainer != null) {
            myContainer.close();
        }

        if (myManager != null) {
            myManager.close();
        }
    } catch (XmlException ce) {
        // Exception handling goes here
    } 

Deleting Indices

To delete an index from a container:

  1. Retrieve the index specification from the container.

  2. Use XmlIndexSpecification.deleteIndex() to delete the index from the index specification.

  3. Set the updated index specification back to the container.

For example:

package dbxml.gettingStarted;

import com.sleepycat.dbxml.XmlContainer;
import com.sleepycat.dbxml.XmlException;
import com.sleepycat.dbxml.XmlIndexSpecification;
import com.sleepycat.dbxml.XmlManager;
import com.sleepycat.dbxml.XmlValue;
...

XmlManager myManager = null;
XmlContainer myContainer = null;

...

try {
    // Get a manager object.
    myManager = new XmlManager();

    // Open a container
    myContainer = 
        myManager.openContainer("exampleData.dbxml");

    // Get the index specification
    XmlIndexSpecification is = myContainer.getIndexSpecification();

    // Delete the index. We're deleting the index from "node1" in
    // the default namespace that has the syntax strategy identified
    // above. 
    is.deleteIndex("", "node1", "node-element-presence-none");

    // Save the index specification back to the container.
    myContainer.setIndexSpecification(is);

    is.delete();

} catch (XmlException e) {
    // Error handling goes here.
} finally {
    try {
        if (myContainer != null) {
            myContainer.close();
        }

        if (myManager != null) {
            myManager.close();
        }
    } catch (XmlException ce) {
        // Exception handling goes here
    } 

Replacing Indices

You can replace the indices maintained for a specific node by using XmlIndexSpecification.replaceIndex(). When you replace the index for a specified node, all of the current indices for that node are deleted and the replacement index strategies that you provide are used in their place.

Note that all the indices for a specific node can be retrieved and specified as a space- or comma-separated list in a single string. So if you set a node-element-equality-string and a node-element-presence index for a given node, then its indices are identified as:

"node-element-equality-string node-element-presence"

For example:

package dbxml.gettingStarted;

import com.sleepycat.dbxml.XmlContainer;
import com.sleepycat.dbxml.XmlException;
import com.sleepycat.dbxml.XmlIndexSpecification;
import com.sleepycat.dbxml.XmlManager;
import com.sleepycat.dbxml.XmlValue;
...

XmlManager myManager = null;
XmlContainer myContainer = null;

...

try {
    // Get a manager object.
    myManager = new XmlManager();

    // Open a container
    myContainer = 
        myManager.openContainer("exampleData.dbxml");

    // Get the index specification
    XmlIndexSpecification is = myContainer.getIndexSpecification();

    // Replace the index.
    String idxString = 
        "node-element-equality-string node-element-presence";
    is.replaceIndex("", "node1", idxString);

    // Save the index specification back to the container.
    myContainer.setIndexSpecification(is);

    is.delete();

} catch (XmlException e) {
    // Error handling goes here.
} finally {
    try {
        if (myContainer != null) {
            myContainer.close();
        }

        if (myManager != null) {
            myManager.close();
        }
    } catch (XmlException ce) {
        // Exception handling goes here
    } 

Examining Container Indices

You can iterate over all the indices in a container using XmlIndexSpecification.next(). This method returns the index in the form of an XmlIndexDeclaration object.

For example:

package dbxml.gettingStarted;

import com.sleepycat.dbxml.XmlContainer;
import com.sleepycat.dbxml.XmlException;
import com.sleepycat.dbxml.XmlIndexSpecification;
import com.sleepycat.dbxml.XmlIndexDeclaration;
import com.sleepycat.dbxml.XmlManager;
import com.sleepycat.dbxml.XmlValue;
...

XmlManager myManager = null;
XmlContainer myContainer = null;

...

try {
    // Get a manager object.
    myManager = new XmlManager();

    // Open a container
    myContainer = 
        myManager.openContainer("exampleData.dbxml");

    // Get the index specification
    XmlIndexSpecification is = myContainer.getIndexSpecification();

    int count = 0;
    XmlIndexDeclaration idxDecl = null;
    while((idxDecl = (idxSpec.next())) != null) {
        System.out.println("For node '" + idxDecl.name +
                           "', found index: '" +
                           idxDecl.index + "'.");
        count ++;
    }
    System.out.println(count + " indices found.");

    is.delete();

} catch (XmlException e) {
    // Error handling goes here.
} finally {
    try {
        if (myContainer != null) {
            myContainer.close();
        }

        if (myManager != null) {
            myManager.close();
        }
    } catch (XmlException ce) {
        // Exception handling goes here
    } 

Working with Default Indices

Default indices are indices that are applied to all applicable nodes in the container that are not otherwise indexed. For example, if you declare a default index for a metadata node, then all metadata nodes will be indexed according to that indexing strategy, unless some other indexing strategy is explicitly set for them. In this way, you can avoid the labor of specifying a given indexing strategy for all occurrences of a specific kind of a node.

You add, delete, and replace default indices using:

  • XmlIndexSpecification.addDefaultIndex()

  • XmlIndexSpecification.deleteDefaultIndex()

  • XmlIndexSpecification.replaceDefaultIndex()

When you work with a default index, you identify only the indexing strategy; you do not identify a URI or node name to which the strategy is to be applied.

Note that just as is the case with other indexing methods, you can use either strings or enumerated types to identify the index strategy.

For example, to add a default index to a container:

package dbxml.gettingStarted;

import com.sleepycat.dbxml.XmlContainer;
import com.sleepycat.dbxml.XmlException;
import com.sleepycat.dbxml.XmlIndexSpecification;
import com.sleepycat.dbxml.XmlManager;
import com.sleepycat.dbxml.XmlValue;
...

XmlManager myManager = null;
XmlContainer myContainer = null;

...

try {
    // Get a manager object.
    myManager = new XmlManager();

    // Open a container
    myContainer = 
        myManager.openContainer("exampleData.dbxml");

    // Get the index specification
    XmlIndexSpecification is = myContainer.getIndexSpecification();

    // Add the default index.
    is.addDefaultIndex("node-metadata-equality-string");

    // Save the index specification back to the container.
    myContainer.setIndexSpecification(is);

    is.delete();

} catch (XmlException e) {
    // Error handling goes here.
} finally {
    try {
        if (myContainer != null) {
            myContainer.close();
        }

        if (myManager != null) {
            myManager.close();
        }
    } catch (XmlException ce) {
        // Exception handling goes here
    } 

Looking Up Indexed Documents

You can retrieve all of the values referenced by an index using an XmlIndexLookup object, which is returned by the XmlManager.createIndexLookup() method. XmlIndexLookup allows you to obtain an XmlResults object that contains all of the nodes or documents for which the identified index has keys. Whether nodes or documents is return depends on several factors:

  • If your container is of type WholedocContainer, then by default entire documents are always returned in this method's results set.

  • If your container is of type NodeContainer then by default this method returns the nodes to which the index's keys refer.

For example, every container is created with a default index that ensures the uniqueness of the document names in your container. The:

  • URI is http://www.sleepycat.com/2002/dbxml.

  • Node name is name.

  • Indexing strategy is unique-node-metadata-equality-string.

Given this, you can efficiently retrieve every document in the container using XmlIndexLookup. as follows:

package dbxml.gettingStarted;

import com.sleepycat.dbxml.XmlContainer;
import com.sleepycat.dbxml.XmlException;
import com.sleepycat.dbxml.XmlIndexLookup;
import com.sleepycat.dbxml.XmlManager;
import com.sleepycat.dbxml.XmlResults;
import com.sleepycat.dbxml.XmlValue;
import com.sleepycat.dbxml.XmlQueryContext;
...

XmlManager myManager = null;
XmlContainer myContainer = null;

...

try {
    // Get a manager object.
    myManager = new XmlManager();

    // Open a container
    myContainer = 
        myManager.openContainer("exampleData.dbxml");

    XmlQueryContext qc = myManager.createQueryContext();

    // Lookup the index
    String uri = "http://www.sleepycat.com/2002/dbxml";
    String name = "name";
    String idxStrategy = "unique-node-metadata-equality-string";

    // Get the XmlIndexLookup Object
    XmlIndexLookup xil = myManager.createIndexLookup(myContainer, uri, 
        name, idxStrategy);

    // Now look it up. This returns every document in the container.
    XmlResults res = xil.execute(qc);

    // Iterate over the results set, printing each document in it
    XmlDocument thedoc = myManager.createDocument();
    while (res.next(thedoc)) {
        System.out.println(thedoc.getName() + ": ");
        System.out.println(thedoc.getContentAsString());
    }

    res.delete();
    xil.delete();
    qc.delete();

} catch (XmlException e) {
    // Error handling goes here.
} finally {
    try {
        if (myContainer != null) {
            myContainer.close();
        }

        if (myManager != null) {
            myManager.close();
        }
    } catch (XmlException ce) {
        // Exception handling goes here
    } 

In the event that you want to lookup an edge index, you must provide the lookup method with both the node and the parent node that together comprise the XML edge.

For example, suppose you have the following document in your container:

<mydoc>
   <node1>
        <node2>
            node2 1 
        </node2>
        <node2>
            node2 2
        </node2>
   </node1>
</mydoc> 

Further suppose you indexed the presence of the node1/node2 edges. In this case, you can lookup the values referred to by this index by doing the following:

package dbxml.gettingStarted;

import com.sleepycat.dbxml.XmlContainer;
import com.sleepycat.dbxml.XmlException;
import com.sleepycat.dbxml.XmlManager;
import com.sleepycat.dbxml.XmlResults;
import com.sleepycat.dbxml.XmlValue;
import com.sleepycat.dbxml.XmlQueryContext;
...

XmlManager myManager = null;
XmlContainer myContainer = null;

...

try {
    // Get a manager object.
    myManager = new XmlManager();

    // Open a container
    myContainer = 
        myManager.openContainer("exampleData.dbxml");

    XmlQueryContext qc = myManager.createQueryContext();

    // Node to lookup
    String uri;
    String name = "node2";

    // Parent node to lookup
    String parentURI;
    String parentName = "node1";

    String idxStrategy = "edge-element-presence";

    // Get the XmlIndexLookup Object
    XmlIndexLookup xil = myManager.createIndexLookup(myContainer, uri,
        name, idxStrategy);

    // Identify the parent node
    xil.setParent(parentURI, parentName);

    // Now look it up. 
    XmlResults res = xil.execute(qc);

    // Iterate over the results set, printing each value in it
    while (res.hasNext()) {
        XmlValue retValue = res.next();
        System.out.println("Found: " + retValue.asString());
    }
    res.delete();
    xil.delete();
    qc.delete();

} catch (XmlException e) {
    // Error handling goes here.
} finally {
    try {
        if (myContainer != null) {
            myContainer.close();
        }

        if (myManager != null) {
            myManager.close();
        }
    } catch (XmlException ce) {
        // Exception handling goes here
    }