 Apache Geode
  
    CHANGELOG
  Apache Geode
  
    CHANGELOG
  
        
  Querying a Partitioned Region on a Single Node
To direct a query to specific partitioned region node, you can execute the query within a function. Use the following steps:
- Implement a function which executes a query using RegionFunctionContext. - /** * This function executes a query using its RegionFunctionContext * which provides a filter on data which should be queried. * */ public class MyFunction extends FunctionAdapter { private final String id; @Override public void execute(FunctionContext context) { Cache cache = CacheFactory.getAnyInstance(); QueryService queryService = cache.getQueryService(); String qstr = (String) context.getArguments(); try { Query query = queryService.newQuery(qstr); //If function is executed on region, context is RegionFunctionContext RegionFunctionContext rContext = (RegionFunctionContext)context; SelectResults results = (SelectResults) query.execute(rContext) //Send the results to function caller node. context.getResultSender().sendResult((ArrayList) (results).asList()); context.getResultSender().lastResult(null); } catch (Exception e) { throw new FunctionException(e); } } @Override public boolean hasResult() { return true; } @Override public boolean isHA() { return false; } public MyFunction(String id) { super(); this.id = id; } @Override public String getId() { return this.id; } }
- Decide on the data you want to query. Based on this decision, you can use - PartitionResolverto configure the organization of buckets to be queried in the Partitioned Region.- For example, let’s say that you have defined the PortfolioKey class: - public class PortfolioKey implements DataSerializable { private int id; private long startValidTime; private long endValidTime private long writtenTime public int getId() { return this.id; } ... }- You could use the - MyPartitionResolverto store all keys with the same ID in the same bucket. This- PartitionResolverhas to be configured at the time of Partition Region creation either declaratively using xml OR using APIs. See Configuring Partitioned Regions for more information.- /** This resolver returns the value of the ID field in the key. With this resolver, * all Portfolios using the same ID are colocated in the same bucket. */ public class MyPartitionResolver implements PartitionResolver, Declarable { public Serializable getRoutingObject(EntryOperation operation) { return operation.getKey().getId(); }
- Execute the function on a client or any other node by setting the filter in the function call. - /** * Execute MyFunction for query on specified keys. * */ public class TestFunctionQuery { public static void main(String[] args) { ResultCollector rcollector = null; PortfolioKey portfolioKey1 = ...; //Filter data based on portfolioKey1 which is the key used in //region.put(portfolioKey1, portfolio1); Set filter = Collections.singleton(portfolioKey1); //Query to get all positions for portfolio ID = 1 String qStr = "SELECT positions FROM /myPartitionRegion WHERE ID = 1"; try { Function func = new MyFunction("testFunction"); Region region = CacheFactory.getAnyInstance().getRegion("myPartitionRegion"); //Function will be routed to one node containing the bucket //for ID=1 and query will execute on that bucket. rcollector = FunctionService .onRegion(region) .setArguments(qStr) .withFilter(filter) .execute(func); Object result = rcollector.getResult(); //Results from one or multiple nodes. ArrayList resultList = (ArrayList)result; List queryResults = new ArrayList(); if (resultList.size()!=0) { for (Object obj: resultList) { if (obj != null) { queryResults.addAll((ArrayList)obj); } } } printResults(queryResults); } catch (FunctionException ex) { getLogger().info(ex); } } }