| --- |
| title: Querying a Partitioned Region on a Single Node |
| --- |
| |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| To direct a query to specific partitioned region node, you can execute the query within a function. Use the following steps: |
| |
| 1. Implement a function which executes a query using RegionFunctionContext. |
| |
| ``` pre |
| /** |
| * 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; |
| } |
| } |
| ``` |
| |
| 2. Decide on the data you want to query. Based on this decision, you can use `PartitionResolver` to configure the organization of buckets to be queried in the Partitioned Region. |
| |
| For example, let's say that you have defined the PortfolioKey class: |
| |
| ``` pre |
| 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 `MyPartitionResolver` to store all keys with the same ID in the same bucket. This `PartitionResolver` has to be configured at the time of Partition Region creation either declaratively using xml OR using APIs. See [Configuring Partitioned Regions](../partitioned_regions/managing_partitioned_regions.html#configure_partitioned_regions) for more information. |
| |
| ``` pre |
| /** 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(); |
| } |
| ``` |
| |
| 3. Execute the function on a client or any other node by setting the filter in the function call. |
| |
| ``` pre |
| /** |
| * 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); |
| } |
| } |
| } |
| ``` |
| |
| |