Apache Igniteの検索（クエリ）をいろいろ試してみる

# Apache Igniteの検索

Igniteの検索は、単なるキャッシュからのGETだけでなく、スキャンクエリ、SQLクエリ（ANSI-99準拠）、およびテキストクエリをサポートしています。

（テキストクエリは興味がないので）
今回はGET、スキャンクエリ、SQLクエリを試してみます。

Apache Igniteのインストール方法は以下の記事を参考にしてください。

[インメモリデータグリッド Apache Igniteを始めてみる（Java）](https://qiita.com/mkyz08/items/81a526827a573ea17805)

# 今回利用するキャッシュ

キャッシュはStringをキーとして、Testmインスタンスを格納しています。
Testmは以下のようにdata1,data2,data3のフィールドを持ちます。

```Testm.java
public class Testm implements Serializable {
    private static final long serialVersionUID = 0L;

    private Long data1;
    private Long data2;
    private Long data3;
```

IgniteCacheのインスタンスは以下のように取得したものを利用しています。

```java

		try (Ignite igniteClient = Ignition.start("XXXX.xml")) {
			final String CACHE_NAME = "TestmCache";

			IgniteCache<String, Testm> cache = igniteClient.cache(CACHE_NAME);
```

# キャッシュのGET

キャッシュからGETする。

```java
	private static void get() {
		Testm data = cache.get("key1");
		logger.info("get data: {}", data.toString());
	}
```

（検索じゃないけど）キャッシュへPUTする。

```java
	private static void put() {
		Testm data = new Testm(1L, 100L, 200L);
		cache.put("key1" , data);
	}
```


# スキャンクエリ

条件（data1が50以上）指定で検索する。
最初に自動で1024件（設定で変更可）がロードされ、QueryCursorにより自動で残りのデータがロードされます。

```java
	private static void queryScan() {
		try (QueryCursor<Entry<String, Testm>> query = cache.query(new ScanQuery<String, Testm>((k, v) -> (v.getData1() >= 50L)))) {
			for (Entry<String, Testm> entry : query) {
				logger.info(entry.getKey() + ":" + entry.getValue());
			}
		}
	}
```

条件（data1が50以上）指定で検索する。全件取得。

```java
	private static void queryScanGetAll() {
		List<Entry<String, Testm>> list = cache.query(new ScanQuery<String, Testm>((k, v) -> (v.getData1() >= 50L))).getAll();
		list.forEach(entry -> logger.info(entry.getKey() + ":" + entry.getValue()));
	}
```

条件（data1が50以上）指定で検索する。キー値のみ取得。

```java
	private static void queryScanOnlyKey() {
		List<String> keys = cache.query(new ScanQuery<String, Testm>(
			    (k, v) -> v.getData1() > 50L),
			    Cache.Entry::getKey
			).getAll();

		keys.forEach(k -> logger.info("key: " + k));
	}
```

条件（data1が50以上）指定で検索する。キー値以外のデータのみ取得。

```java
	private static void queryScanOnlyValue() {
		List<Testm> keys = cache.query(new ScanQuery<String, Testm>(
			    (k, v) -> v.getData1() > 50L),
			    Cache.Entry::getValue
			).getAll();

		keys.forEach(v -> logger.info("value: " + v.toString()));
	}
```


# SQLクエリ

Where句指定で検索する。

```java
	private static void sqlQuery() {
		SqlQuery<String, Testm> sql = new SqlQuery<String, Testm>(Testm.class, "data1 > ?");

		try (QueryCursor<Entry<String, Testm>> cursor = cache.query(sql.setArgs(50L))) {
		  for (Entry<String, Testm> entry : cursor)
			  logger.info(entry.getKey() + ": " + entry.getValue());
		}
	}
```

SQL（SELECT）で検索する。

```java
	private static void sqlFieldsQuery() {
		SqlFieldsQuery sql = new SqlFieldsQuery("select data1, data2 from Testm where data1 > ?");

		try (QueryCursor<List<?>> cursor = cache.query(sql.setArgs(50L))) {
			  for (List<?> row : cursor)
			    logger.info("data1: " + row.get(0));
			}
	}
```

INSERT/MERGE/UPDATE/DELETEも使えます。
詳細は以下の公式サイトのページを参照。
https://apacheignite-sql.readme.io/docs/dml

# 最後に

今回は利用しませんでしたが、Igniteではインデックスを利用することができます。
キー値以外の条件で検索する場合は、インデックスを作成しておかないと検索に時間がかかるため、インデックス設計も重要になります。

また、SQLについては、v2.6ではトランザクションに対応していませんが、今後対応が予定されています。色々と制限はあるかもしれませんが・・・