---
title: Remote Queries
---

<!--
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.
-->

Use the remote query API to query your cached data stored on a cache server. 

## <a id="RemoteQueryBasics"></a>Remote Query Basics

Queries are evaluated and executed on the cache server, and the results are returned to the client.
You can optimize your queries by defining indexes on the cache server.

Querying and indexing operate only on remote cache server contents.

### <a id="QueryLanguage"></a>Query language: OQL
<%=vars.product_name%> provides a SQL-like querying language called OQL that allows you to access data stored in <%=vars.product_name%> regions.
OQL is very similar to SQL, but OQL allows you to query complex objects, object attributes, and methods.

In the context of a query, specify the name of a region by its full path, starting with a slash (`/`).

The query language supports drilling down into nested object structures.
Nested data collections can be explicitly referenced in the FROM clause of a query.

A query execution returns its results as either a `ResultSet` or a `StructSet`. 

Query language features and grammar are described in the <%=vars.product_name%> manual at
[Querying](geodeman/developing/querying_basics/chapter_overview.html).

### <a id="CreatingIndexes"></a>Creating Indexes

Indexes can provide significant performance gains for query execution. You create and maintain indexes on the cache server.
For detailed information about working with indexes configured on a cache server, 
see [Working with Indexes](geodeman/developing/query_index/query_index.html) in the server's documentation.

## <a id="RemoteQueryAPI"></a>Remote Query API

This section gives a general overview of the interfaces and classes that are provided by the query package API.

### <a id="Query"></a>Query

You must create a `Query` object for each new query. The `Query` interface provides methods for
managing the compilation and execution of queries, and for retrieving an existing query string.

A `Query` is obtained from a `QueryService`, which is obtained from one of two sources:

- To create a `Query` that operates on the <%=vars.product_name%> server, use `apache::geode::client::Pool::getQueryService()` to instantiate a `QueryService` obtained from a `Pool`.

- To create a `Query` that operates on your application's local cache, use `apache::geode::client::Cache::getQueryService()` to instantiate a `QueryService` obtained from a `Cache`.

### <a id="ExecutingAQuery"></a>Executing a Query from the Client

The essential steps to create and execute a query are:

1.  Create an instance of the `QueryService` class. If you are using the pool API (recommended), you should obtain the `QueryService` from the pool.
1.  Create a `Query` instance that is compatible with the OQL specification.
1.  Use the `Query.execute()` method to submit the query string to the cache server. The server
   remotely evaluates the query string and returns the results to the client.
1.  Iterate through the returned objects.

### <a id="CppQueryExample"></a>C++ Query Example

These C++ code excerpts are from the `examples/cpp/remotequery` example included in your client
distribution. See the example for full context.

Following the steps listed above,

  1. Obtain a `QueryService` object from the connection pool:

    ```
    std::shared_ptr<QueryService> queryService = nullptr;
    queryService = pool->getQueryService();
    ```

  1. Create a `Query` object by calling `QueryService.newQuery()`, specifying your OQL query as a string parameter:

    ```
    auto query = queryService->newQuery("SELECT * FROM /custom_orders WHERE quantity > 30");    
    ```

  1. Execute the query. Collect the query output, returned as either a `ResultSet` or a `StructSet`, and iterate through the results:

    ```
    auto queryResults = query->execute();

    for (auto&& value : *queryResults) {
      auto&& order = std::dynamic_pointer_cast<Order>(value);
      std::cout << order->toString() << std::endl;
    }
    ```

