ObjectStore provides a mechanism for querying COM.odi.util.Collection objects. A query applies a predicate expression (an expression that evaluates to a boolean result) to all elements in a collection. The query returns a subset collection that contains all elements for which the expression is true.
Using Indexes to Speed Query Performance
Querying Collections
Using queries involves a two-step process:
The query string is a predicate expression, which is defined with native Java. There is no SQL (Structured Query Language) or JDBC required. Query strings can include standard Java arithmetic, conditional, and relational operators, as well as simple methods. The following example shows creation of a query that finds all interests where the interest name is "wine":
Query query = new Query(Interest.class, "getName() == \"wine\"");This example uses a public method instead of a field. This allows the Interest name field to remain private and preserves the encapsulation of the interest's state. If the name field was public, you could specify the query like this:
Query query = new Query(Interest.class, "name == \"wine\"");When you create a query, you do not bind it to a particular collection. You can create a query, run it once, and throw it away. Alternatively, you can reuse a query multiple times against the same collection, or against different collections.
You can also use variables in query strings. See Specifying Variables in Queries.
Running Queries Against Collections
You run a query against a specific collection with a call to the Query.select() method. The call specifies the collection to be queried. For example, after you define a query as in the previous section, you can run that query like this:
Collection wine = query.select(allInterests);In this example, the query tests the elements in the set of allInterests to find the elements whose name is wine.
String interestName = "wine"; FreeVariables freeV = new FreeVariables(); freeV.put("x", String.class); Query query = new Query(Interest.class, "getName() == x", freeV); FreeVariableBindings freeVB = new FreeVariableBindings(); freeVB.put("x", interestName); Collection queryResults = query.select( allInterests.values(), freeVB);First, create a FreeVariables list and add a variable, x in this example, to it. When you add the variable, you specify the type of the variable. In this case, the type of x is String because it is going to represent a String in the query string. When you create the query,
/** * Get all users with a particular interest. * * @param interestName: The name of the interest. * * @return An array of names of users with this interest. **/ public static String[] find Users(String interestName) throws PersonalizationException { Transaction tr = Transaction.begin(ObjectStore.READONLY); String queryString = "getName() == \"" + interestName + "\""; Query interestQuery = new Query(Interest.class, queryString); Collection interests = interestQuery.select(allInterests); String[] users = new String[interests.size()]; int index = 0; Iterator iter = interests.iterator(); while (iter.hasNext()) users[index++] = ((Interest)iter.next()).getUser().getName(); tr.commit(ObjectStore.RETAIN_READONLY); return users; }
While querying is supported on all COM.odi.util collections, only COM.odi.util.OSTreeSet already implements the IndexedCollection interface. This means that if you want to add an index to another type (other than OSTreeSet) of collection, you must define a collection class that implements the IndexedCollection interface.
To use an index, you create it and then specifiy the indexed field or method in a query. A query can include both indexed fields/methods and nonindexed fields/methods. ObjectStore evaluates the indexed fields and methods first and establishes a preliminary result set. ObjectStore then applies the nonindexed fields/methods to the elements in the preliminary result set.
addIndex(Class, String) addIndex(Class, String, boolean, boolean)The Class argument indicates the element type to which the index applies. The String indicates the element member to be indexed.
The optional boolean arguments allow you to specify whether the index is ordered and whether it allows duplicates. If you do not specify the boolean arguments, the index is unordered and it allows duplicates.
db.createRoot("allInterests", allInterests = new OSTreeSet(db)); allInterests.addIndex(Interest.class, "getName()");
For example, suppose you insert Jones into a collection called userCollection and then you build an index for userCollection on the email field. If you remove Jones from the collection, ObjectStore updates the email index so it no longer includes the entry for the Jones object. However, if you leave Jones in the collection, but change Jones' email address, you must manually update the index to contain the correct email entry.
To update an index, you must
User jones = /* assume jones references Jones */ userCollection.removeFromIndex(User.class, "email", jones); jones.setEmail("jones@objectdesign.com"); userCollection.addToIndex(User.class, "email", jones);
Updated: 10/07/98 07:05:56