This exercise illustrates how you can simplify Java expressions that use aggregations and filters by using the Coherence createFilter
and createExtractor
factory methods in the QueryHelper
class.
In Chapter 5, "Loading Data Into a Cache," you created a file, QueryExample.java
, that used a variety of filters, such as AlwaysFilter
, LikeFilter
, and EqualsFilter
, to pull and aggregate information from the cache. The file also created indexes on the data by using a variety of specialized ValueExtractors
: ChainedExtractors
, KeyExtractors
, and ReflectionExtractors
. This created some verbose Java statements. These statements can be simplified by using the QueryHelper
API.
This chapter contains the following sections:
To simplify filter and extractor statements, and the way in which you interact with the Coherence caches, Coherence provides the QueryHelper
API. QueryHelper
(com.tangosol.util.QueryHelper
) is a utility class that provides a set of createFilter
and createExtractor
factory methods that can build instances of Filter
and ValueExtractor
. The methods in the class accept a String data type that specifies the creation of rich Filters in a format that is familiar to anyone who understands SQL WHERE
clauses.
For example, the following statement uses createFilter(String s)
to construct a filter for employees who live in Massachusetts but work in another state.
.. QueryHelper.createFilter("homeAddress.state = 'MA' and workAddress.state !='MA'") ...
This statement is more simple and easier to read than the equivalent filter and extractor statement using the Coherence API:
new AndFilter(new EqualsFilter("getHomeAddress.getState", "MA"), new NotEqualsFilter("getWorkAddress.getState", "MA"))
For more information, see the Javadoc for the QueryHelper
API. For information on the syntax of the WHERE
clause within the Coherence Query Language, see "Using Coherence Query Language" in Oracle Fusion Middleware Developing Applications with Oracle Coherence.
This section describes how you can simplify the indexes, cache calls, and aggregations in the QueryExample.java
file that you created in the previous chapter.
Import the QueryHelper
API into the QueryExample.java
file as a static class.
import static com.tangosol.util.QueryHelper.*;
Comment out the imports for the ChainedExtractor
, KeyExtractor
, and ReflectionExtractor
classes.
Comment out the imports for the AlwaysFilter
, AndFilter
, EqualsFilter
, GreaterFilter
, LikeFilter
, and NotEqualsFilter
classes.
In the cache.addIndex
statements, replace instances of ReflectionExtractor
with createExtractor
from the QueryHelper API.
Table 6-1 lists the ReflectionExtractor
instances and their createExtractor
equivalents.
Table 6-1 ReflectionExtractors and Their Equivalent createExtractor Statements
Replace This ReflectionExtractor Statement ... | With the Equivalent createExtractor Statement ... |
---|---|
|
|
|
|
|
|
|
|
Replace the calls to the *Filter
methods in the setResults
statements with calls to createFilter
with the appropriate Coherence Query Language.
Table 6-2 lists the *Filter
instances and their createFilter
equivalents.
Table 6-2 *Filter Statements and Their Equivalent createFilter Statements in Queries
Replace This *Filter Statement ... | With the Equivalent createFilter Statement ... |
---|---|
|
|
|
|
|
|
|
|
|
|
Replace the calls to the *Filter
methods in the aggregate
statements with calls to createFilter
with the appropriate Coherence Query Language.
Table 6-3 lists the *Filter
instances and their createFilter
equivalents.
Table 6-3 Filter Statements and Their Equivalent createFilter Statements in Aggregations
Replace This *Filter Statement ... | With the Equivalent createFilter Statement ... |
---|---|
|
|
|
|
|
|
|
|
When you are finished with the code replacements, QueryExample.java
looks similar to Example 6-1.
Example 6-1 Edited QueryExample File
package com.oracle.handson; import com.tangosol.net.CacheFactory; import com.tangosol.net.NamedCache; import com.tangosol.util.Filter; import static com.tangosol.util.QueryHelper.*; import com.tangosol.util.aggregator.Count; // import com.tangosol.util.extractor.ChainedExtractor; // import com.tangosol.util.extractor.KeyExtractor; // import com.tangosol.util.extractor.ReflectionExtractor; // import com.tangosol.util.aggregator.Count; import com.tangosol.util.aggregator.DoubleAverage; import com.tangosol.util.aggregator.LongMax; import com.tangosol.util.aggregator.LongMin; // import com.tangosol.util.filter.AlwaysFilter; // import com.tangosol.util.filter.AndFilter; // import com.tangosol.util.filter.EqualsFilter; // import com.tangosol.util.filter.GreaterFilter; // import com.tangosol.util.filter.LikeFilter; // import com.tangosol.util.filter.NotEqualsFilter; import java.util.Iterator; import java.util.Set; /** * QueryExample runs sample queries for contacts. * */ public class QueryExample{ // ----- QueryExample methods --------------------------------------- public static void main(String[] args) { NamedCache cache = CacheFactory.getCache("ContactsCache"); query(cache); } /** * Perform the example queries * */ public static void query(NamedCache cache) { // Add indexes to make queries more efficient // ReflectionExtractor reflectAddrHome = // new ReflectionExtractor("getHomeAddress"); // Add an index for the age // cache.addIndex(new ReflectionExtractor("getAge"), true, null); cache.addIndex(createExtractor("age"), true, null); // Add index for state within home address // cache.addIndex(new ChainedExtractor(reflectAddrHome, // new ReflectionExtractor("getState")), true, null); cache.addIndex(createExtractor("homeAddress.state"), false, null); // Add index for state within work address // cache.addIndex(new ChainedExtractor( // new ReflectionExtractor("getWorkAddress"), // new ReflectionExtractor("getState")), true, null); cache.addIndex(createExtractor("workAddress.state"),false, null); // Add index for city within home address // cache.addIndex(new ChainedExtractor(reflectAddrHome, // new ReflectionExtractor("getCity")), true, null); cache.addIndex(createExtractor("homeAddress.city"), true, null); // Find all contacts who live in Massachusetts // Set setResults = cache.entrySet(new EqualsFilter( // "getHomeAddress.getState", "MA")); Set setResults = cache.entrySet(createFilter("homeAddress.state = 'MA'")); printResults("MA Residents", setResults); // Find all contacts who live in Massachusetts and work elsewhere // setResults = cache.entrySet(new AndFilter( // new EqualsFilter("getHomeAddress.getState", "MA"), // new NotEqualsFilter("getWorkAddress.getState", "MA"))); setResults = cache.entrySet(createFilter("homeAddress.state is 'MA' and workAddress is not 'MA'")); printResults("MA Residents, Work Elsewhere", setResults); // Find all contacts whose city name begins with 'S' // setResults = cache.entrySet(new LikeFilter("getHomeAddress.getCity", // "S%")); setResults = cache.entrySet(createFilter("homeAddress.city like 'S%'")); printResults("City Begins with S", setResults); final int nAge = 42; Object[] aEnv = new Object[] {new Integer(nAge)}; // Find all contacts who are older than nAge // setResults = cache.entrySet(new GreaterFilter("getAge", nAge)); setResults = cache.entrySet(createFilter("age > ?1",aEnv)); printResults("Age > " + nAge, setResults); // Find all contacts with last name beginning with 'S' that live // in Massachusetts. Uses both key and value in the query. // setResults = cache.entrySet(new AndFilter( // new LikeFilter(new KeyExtractor("getLastName"), "S%", // (char) 0, false), // new EqualsFilter("getHomeAddress.getState", "MA"))); setResults = cache.entrySet(createFilter("key(lastName) like 'S%' and homeAddress.state = 'MA'")); setResults = cache.entrySet(createFilter("key().lastName like 'S%' and homeAddress.state = 'MA'")); printResults("Last Name Begins with S and State Is MA", setResults); // Count contacts who are older than nAge // System.out.println("count > " + nAge + ": "+ // cache.aggregate(new GreaterFilter("getAge", nAge), new Count())); System.out.println("count > " + nAge + ": " + cache.aggregate( createFilter("age > ?1", aEnv), new Count())); // Find minimum age // System.out.println("min age: " + cache.aggregate(AlwaysFilter.INSTANCE, new LongMin("getAge"))); Filter always = createFilter("true"); System.out.println("min age: " + cache.aggregate(always, new LongMin("getAge"))); // Calculate average age // System.out.println("avg age: " + cache.aggregate(AlwaysFilter.INSTANCE, new DoubleAverage("getAge"))); System.out.println("avg age: " + cache.aggregate(always, new DoubleAverage("getAge"))); // Find maximum age // System.out.println("max age: " + // cache.aggregate(AlwaysFilter.INSTANCE, new LongMax("getAge"))); System.out.println("max age: " + cache.aggregate(always, new LongMax("getAge"))); System.out.println("------QueryLanguageExample completed------"); } /** * Print results of the query * * @param sTitle the title that describes the results * @param setResults a set of query results */ private static void printResults(String sTitle, Set setResults) { System.out.println(sTitle); for (Iterator iter = setResults.iterator(); iter.hasNext(); ) { System.out.println(iter.next()); } } }
To rerun the query example:
Stop any running cache servers. See "Stopping Cache Servers" for more information.
Restart the ContactsCacheServer
.
Run the DataGenerator
, LoaderExample
, and QueryExample
files.
After printing all of the contact information in the cache, it displays the results of the queries. The results should look similar to the following examples.
Note:
The DataGenerator
program produces random names, cities and birthdates. Your output may be different.
Example 6-2 illustrates the output of the MA Residents filter.
Example 6-2 Output of the MA Residents Filter
...
MA Residents
ConverterEntry{Key="John Hwdrrls", Value="John Hwdrrls
Addresses
Home: 369 Beacon St.
Fetggv, MA 24372
US
Work: Yoyodyne Propulsion Systems
330 Lectroid Rd.
Grover's Mill, NE 84499
US
Telephone Numbers
work: +11 88 331 2307913
home: +11 64 86 2489621
Birth Date: 1976-12-29"}
...
Example 6-3 illustrates the output of the MA Residents, Work Elsewhere filter.
Example 6-3 Output of the MA Residents, Work Elsewhere Filter
...
MA Residents, Work Elsewhere
ConverterEntry{Key="John Hwdrrls", Value="John Hwdrrls
Addresses
Home: 369 Beacon St.
Fetggv, MA 24372
US
Work: Yoyodyne Propulsion Systems
330 Lectroid Rd.
Grover's Mill, NE 84499
US
Telephone Numbers
work: +11 88 331 2307913
home: +11 64 86 2489621
Birth Date: 1976-12-29"}
...
Example 6-4 illustrates the output of the City Begins with S filter.
Example 6-4 Output of the City Begins with S Filter
...
City Begins with S
ConverterEntry{Key="John Pzek", Value="John Pzek
Addresses
Home: 309 Beacon St.
Saqrgy, OH 81353
US
Work: Yoyodyne Propulsion Systems
330 Lectroid Rd.
Grover's Mill, CT 78117
US
Telephone Numbers
work: +11 28 790 2035988
home: +11 61 470 7634708
Birth Date: 1971-12-31"}
...
Example 6-5 illustrates the output of the age greater than 42 filter.
Example 6-5 Output of the Age Greater than 42 Filter
...
Age > 42
ConverterEntry{Key="John Gddurqqziy", Value="John Gddurqqziy
Addresses
Home: 613 Beacon St.
Cxyskdo, DE 28968
US
Work: Yoyodyne Propulsion Systems
330 Lectroid Rd.
Grover's Mill, SD 07959
US
Telephone Numbers
work: +11 31 768 5136041
home: +11 87 22 3851589
Birth Date: 1958-01-03"}
...
Example 6-6 illustrates the output of the Last Name Begins with S and State is MA filter and the output of the aggregators.
Example 6-6 Output of the State and Age Aggregators
Last Name Begins with S and State Is MA ConverterEntry{Key="John Syaqlojl", Value="John SyaqlojlAddressesHome: 810 Beacon St.Rgtaljwph, MA 07471USWork: 200 Newbury St.Yoyodyne, Ltd.Boston, MA 02116USTelephone Numberswork: +11 37 18 1767648home: +11 98 155 1073866Birth Date: 1974-12-30"} ... count > 42: 446 min age: 22 avg age: 41.126 max age: 61