// 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.
= Using Cache Queries

:javaFile: {javaCodeDir}/UsingScanQueries.java
:dotnetFile: code-snippets/dotnet/UsingScanQueries.cs
// rewrite

== Overview
`IgniteCache` has several query methods, all of which receive a subclass of the `Query` class and return a `QueryCursor`.
Available types of queries: `ScanQuery`, `IndexQuery`, `TextQuery`.

A `Query` represents an abstract paginated query to be executed on a cache.
The page size is configurable via the `Query.setPageSize(...)` method (default is 1024).


`QueryCursor` represents the query result set and allows for transparent page-by-page iteration.
When a user starts iterating over the last page, `QueryCursos` automatically requests the next page in the background.
For cases when pagination is not needed, you can use the `QueryCursor.getAll()` method, which fetches the entries and stores them in a collection.

[NOTE]
====
[discrete]
=== Closing Cursors
Cursors close automatically when you call the `QueryCursor.getAll()` method. If you are iterating over the cursor in a for loop or explicitly getting an `Iterator`, you must close the cursor explicitly or use a  try-with-resources statement.
====


== Executing Scan Queries

A scan query is a simple search query used to retrieve data from a cache in a distributed manner. When executed without parameters, a scan query returns all entries from the cache.

[tabs]
--
tab:Java[]
[source,java]
----
include::{javaFile}[tag=scanQry,indent=0]
----

tab:C#/.NET[]
[source,csharp]
----
include::{dotnetFile}[tag=scanQry1,indent=0]
----

tab:C++[]
[source,cpp]
----
include::code-snippets/cpp/src/scan_query.cpp[tag=query-cursor,indent=0]
----
--


Scan queries return entries that match a predicate, if specified. The predicate is applied on the remote nodes.

[tabs]
--
tab:Java[]
[source,java]
----
include::{javaFile}[tag=predicate,indent=0]
----
tab:C#/.NET[]
[source,csharp]
----
include::{dotnetFile}[tag=scanQry2,indent=0]
----
tab:C++[unsupported]
--

Scan queries also support an optional transformer closure which lets you convert the entry on the server node before sending it back. This is useful, for example, when you want to fetch only several fields of a large object and want to minimize the network traffic. The example below shows how to fetch only the keys without sending the values.

[tabs]
--

tab:Java[]
[source,java]
----
include::{javaFile}[tag=transformer,indent=0]
----
tab:C#/.NET[unsupported]
tab:C++[unsupported]
--

== Local Scan Query

By default, a scan query is distributed to all nodes.
However, you can execute the query locally, in which case the query runs against the data stored on the local node (i.e. the node where the query is executed).

[tabs]
--
tab:Java[]
[source,java]
----
include::{javaFile}[tag=localQuery,indent=0]
----
tab:C#/.NET[]
[source,csharp]
----
include::{dotnetFile}[tag=scanQryLocal,indent=0]
----
tab:C++[]
[source,cpp]
----
include::code-snippets/cpp/src/scan_query.cpp[tag=set-local,indent=0]
----
--

== Executing Index Queries

[WARNING]
====
[discrete]
Experimental API. Introduced since Apache Ignite 2.12. Only Java API is supported. Please send your questions and bug reports
to user@ignite.apache.org.
====

Index queries work over distributed indexes and retrieve cache entries that match the specified query. `QueryCursor`
delivers sorted cache entries by the order defined for queried index. `IndexQuery` can be used if a low amount of data
matches filtering criteria. For such cases, `ScanQuery` usage is not optimal: it firstly extracts all cache entries and
then applies a filter to them. `IndexQuery` relies on index tree structure and filters most of the entries without extracting.

[source,java]
----
include::{javaFile}[tag=idxQry,indent=0]
----

Index query criteria are defined in `IndexQueryCriteriaBuilder`. The goal of the criteria is to build a valid range to
traverse the index tree. For this reason, criteria fields have to match the specified index. For example, if there is an
index defined with (A, B) set, then valid criteria sets are (A) and (A, B). Criteria with the single (B) field are invalid
because the field (B) is not a prefix set of the specified index fields, and it's impossible to build a narrow index range
with it.

[NOTE]
====
Criteria are joined by the AND operator. It is also possible to use multiple criteria for the same field.
====

[source,java]
----
include::{javaFile}[tag=idxQryMultipleCriteria,indent=0]
----

The index name is an optional parameter. In this case, Ignite tries to figure out the index by itself using specified criteria fields.

[source,java]
----
include::{javaFile}[tag=idxQryNoIdxName,indent=0]
----

For the empty criteria list, a full scan of the specified index is performed. If index name is also not specified, then the
PrimaryKey index is used.

=== Additional filtering

`IndexQuery` also supports an optional predicate, the same as `ScanQuery` has. It's suitable for additional cache entry
filtering in cases when a filter doesn't match an index tree range. For example, it contains some logic, the "OR"
operations, or fields that are not the part of the index.

[source,java]
----
include::{javaFile}[tag=idxQryFilter,indent=0]
----

== Related Topics

* link:restapi#sql-scan-query-execute[Execute scan query via REST API]
* link:events/events#cache-query-events[Cache Query Events]
* link:SQL/indexes[Defining Indexes]
