11.3. 検索
Ickle クエリー言語を使用して、ライブラリーおよびリモートクライアント/サーバーモードの両方でリレーショナルおよびフルテキストクエリーを作成します。
API を使用するには、まず QueryFactory をキャッシュに取得してから、.create()
メソッドを呼び出し、クエリーで使用する文字列を渡します。各 QueryFactory
インスタンスは Search
と同じ Cache
インスタンスにバインドされますが、それ以外の場合は、複数のクエリーを並行して作成するために使用できるステートレスおよびスレッドセーフオブジェクトになります。
以下に例を示します。
// Remote Query, using protobuf QueryFactory qf = org.infinispan.client.hotrod.Search.getQueryFactory(remoteCache); Query q = qf.create("from sample_bank_account.Transaction where amount > 20"); // Embedded Query using Java Objects QueryFactory qf = org.infinispan.query.Search.getQueryFactory(cache); Query q = qf.create("from com.acme.Book where price > 20"); // Execute the query QueryResult<Book> queryResult = q.execute();
クエリーは常に単一のエンティティータイプをターゲットにし、単一のキャッシュの内容に対して評価されます。複数のキャッシュでクエリーを実行したり、複数のエンティティータイプ (結合) を対象とするクエリーを作成したりすることは、サポートされていません。
クエリーの実行と結果のフェッチは、Query
オブジェクトの run()
メソッドを呼び出すのと同じくらい簡単です。実行後に、同じインスタンスで run()
を呼び出すと、クエリーを再実行します。
11.3.1. ページネーション
Query.maxResults(int maxResults)
を使用して、返される結果の数を制限することができます。これを Query.startOffset(long startOffset)
と組み合わせて使用すると、結果セットのページネーションを実現できます。
// sorted by year and match all books that have "clustering" in their title // and return the third page of 10 results Query<Book> query = queryFactory.create("FROM com.acme.Book WHERE title like '%clustering%' ORDER BY year").startOffset(20).maxResults(10)
11.3.2. ヒット数
QueryResult
オブジェクトには、ページネーションパラメーターに関係なく、クエリーの結果の合計数を返すための .hitCount()
メソッドがあります。ヒット数は、パフォーマンス上の理由から、インデックス付きクエリーでのみ使用できます。
11.3.3. 反復
Query
オブジェクトには、結果を遅延して取得するための .iterator()
メソッドがあります。使用後に閉じる必要がある CloseableIterator
のインスタンスを返します。
リモートクエリーの反復サポートは現在制限されています。反復する前に、最初にすべてのエントリーをクライアントにフェッチするためです。
11.3.4. 名前付きクエリーパラメーターの使用
実行ごとに新しい Query オブジェクトを作成する代わりに、実行前に実際の値に置き換えることができる名前付きパラメーターをクエリーに含めることができます。これにより、クエリーを 1 度定義し、複数回効率的に実行できます。パラメーターは、Operator の右側でのみ使用でき、通常の定数値ではなく、org.infinispan.query.dsl.Expression.param(String paramName)
メソッドによって生成されたオブジェクトを Operator に提供することで、クエリーの作成時に定義されます。パラメーターが定義されたら、以下の例に示すように Query.setParameter(parameterName, value)
または Query.setParameters(parameterMap)
のいずれかを呼び出すことで設定できます。
QueryFactory queryFactory = Search.getQueryFactory(cache); // Defining a query to search for various authors and publication years Query<Book> query = queryFactory.create("SELECT title FROM com.acme.Book WHERE author = :authorName AND publicationYear = :publicationYear").build(); // Set actual parameter values query.setParameter("authorName", "Doe"); query.setParameter("publicationYear", 2010); // Execute the query List<Book> found = query.list();
または、実際のパラメーター値のマップを指定して、複数のパラメーターを一度に設定することもできます。
複数の名前付きパラメーターを一度に設定する
Map<String, Object> parameterMap = new HashMap<>(); parameterMap.put("authorName", "Doe"); parameterMap.put("publicationYear", 2010); query.setParameters(parameterMap);
クエリーの解析、検証、および実行計画の作業の大部分は、パラメーターでのクエリーの最初の実行時に実行されます。この作業は後続の実行時には繰り返し行われないため、クエリーパラメーターではなく定数値を使用した同様のクエリーの場合よりもパフォーマンスが向上します。
11.3.5. Ickle クエリー言語パーサー構文
Ickle クエリー言語は、フルテキスト用のいくつかのエクステンションを持つ JPQL クエリー言語の小さなサブセットです。
パーサー構文には、以下のような重要なルールがあります。
- 空白は重要ではありません。
- フィールド名ではワイルドカードはサポートされません。
- デフォルトのフィールドがないため、フィールド名またはパスは必ず指定する必要があります。
-
&&
および||
は、フルテキストと JPA 述語の両方で、AND
またはOR
の代わりに使用できます。 -
!
はNOT
の代わりに使用できます。 -
足りないブール値 Operator は
OR
として解釈されます。 - 文字列の用語は、一重引用符または二重引用符で囲む必要があります。
- ファジー性とブースティングは任意の順序で受け入れられず、常にファジー性が最初になります。
-
<>
の代わりに!=
が許可されます。 -
ブーディングは、
>
、>=
、<
、⇐
Operator には適用できません。同じ結果を達成するために範囲を使用することができます。
11.3.5.1. Operator のフィルタリング
Ickle はインデックス化されたフィールドとインデックス化されていないフィールドの両方に使用できる多くの Operator のフィルタリングをサポートします。
Operator | 説明 | 例 |
---|---|---|
in | 左のオペランドが引数として指定された値のコレクションからの要素のいずれかと等しいことを確認します。 | FROM Book WHERE isbn IN ('ZZ', 'X1234') |
like | (文字列として想定される) 左側の引数が、JPA ルールに準拠するワイルドカードパターンと一致することを確認します。 | FROM Book WHERE title LIKE '%Java%' |
= | 左側の引数が指定の値と完全に一致することを確認します。 | FROM Book WHERE name = 'Programming Java' |
!= | 左側の引数が指定の値とは異なることを確認します。 | FROM Book WHERE language != 'English' |
> | 左側の引数が指定の値よりも大きいことを確認します。 | FROM Book WHERE price > 20 |
>= | 左側の引数が指定の値以上であることを確認します。 | FROM Book WHERE price >= 20 |
< | 左側の引数が指定の値未満であることを確認します。 | FROM Book WHERE year < 2012 |
⇐ | 左側の引数が指定の値以下であることを確認します。 | FROM Book WHERE price ⇐ 50 |
between | 左側の引数が指定された範囲の制限の間にあることを確認します。 | FROM Book WHERE price BETWEEN 50 AND 100 |
11.3.5.2. ブール値の条件
以下の例では、複数の属性条件を論理結合 (and
) および非結合 (or
) 演算子と組み合わせて、より複雑な条件を作成する方法を示しています。ブール値演算子のよく知られる演算子の優先順位ルールがここで適用されるため、Operator の順序は関連性がありません。ここで、or
が最初に呼び出された場合でも、and
Operator の優先順位は or
よりも高くなります。
# match all books that have "Data Grid" in their title # or have an author named "Manik" and their description contains "clustering" FROM com.acme.Book WHERE title LIKE '%Data Grid%' OR author.name = 'Manik' AND description like '%clustering%'
ブール値の否定は論理演算子の中で優先され、次の単純な属性条件にのみ適用されます。
# match all books that do not have "Data Grid" in their title and are authored by "Manik" FROM com.acme.Book WHERE title != 'Data Grid' AND author.name = 'Manik'
11.3.5.3. ネストされた条件
論理演算子の優先順位の変更は、括弧を使用して行います。
# match all books that have an author named "Manik" and their title contains # "Data Grid" or their description contains "clustering" FROM com.acme.Book WHERE author.name = 'Manik' AND ( title like '%Data Grid%' OR description like '% clustering%')
11.3.5.4. 属性の選択
一部のユースケースでは、属性のごく一部のみがアプリケーションによって実際に使用されている場合、特にドメインエンティティーにエンティティーが埋め込まれている場合、ドメインオブジェクト全体を返すのはやり過ぎです。クエリー言語を使用すると、プロジェクションを返す属性 (または属性パス) のサブセットを指定できます。デプロイメントが使用される場合、QueryResult.list()
はドメインエンティティー全体を返しませんが、Object[]
の List
(プロジェクト化された属性に対応する配列) を返します。
# match all books that have "Data Grid" in their title or description # and return only their title and publication year SELECT title, publicationYear FROM com.acme.Book WHERE title like '%Data Grid%' OR description like '%Data Grid%'
11.3.5.5. ソート
1 つ以上の属性または属性パスに基づいて結果の順序は ORDER BY
句で行われます。複数の並べ替え基準が指定されている場合は、順序によって優先順位が決まります。
# match all books that have "Data Grid" in their title or description # and return them sorted by the publication year and title FROM com.acme.Book WHERE title like '%Data Grid%' ORDER BY publicationYear DESC, title ASC
11.3.5.6. グループ化およびアグリゲーション
Data Grid には、グループ化フィールドのセットに従ってクエリー結果をグループ化し、各グループに分類される値のセットに集計関数を適用することにより、各グループからの結果の集計を構築する機能があります。グループ化と集計は、プロジェクションクエリー (SELECT 句に 1 つ以上のフィールドがあるクエリー) にのみ適用できます。
サポートされる集約は avg、sum、count、max および min です。
グループ化フィールドセットは GROUP BY
句で指定し、グループ化フィールドの定義に使用される順番は関係ありません。プロジェクションで選択されたすべてのフィールドは、グループ化フィールドであるか、以下で説明するグループ化関数の 1 つを使用して集約される必要があります。Projection フィールドは集約され、同時にグループ化に使用できます。グループ化フィールドのみを選択し、集計フィールドは選択しないクエリーは有効です。例:ブックマークは作成者別にグループ化し、それらをカウントします。
SELECT author, COUNT(title) FROM com.acme.Book WHERE title LIKE '%engine%' GROUP BY author
選択したすべてのフィールドに集計関数が適用され、グループ化にフィールドが使用されないプロジェクションクエリーが許可されます。この場合、集計は、単一のグローバルグループが存在するかのようにグローバルに計算されます。
11.3.5.7. 集約
以下の集約関数をフィールドに適用できます。
-
avg()
- 一連の数字の平均を計算します。許可される値は、java.lang.Number
のプリミティブ番号およびインスタンスです。結果はjava.lang.Double
で表されます。null 以外の値がない場合、結果は代わりにnull
になります。 -
avg()
- null 以外の行の数をカウントし、java.lang.Long
を返します。null 以外の値がない場合、結果は代わりに0
になります。 -
max()
- 見つかった最も大きな値を返します。許可される値はjava.lang.Comparable
のインスタンスである必要があります。null 以外の値がない場合、結果は代わりにnull
になります。 -
min()
- 見つかった最小値を返します。許可される値はjava.lang.Comparable
のインスタンスである必要があります。null 以外の値がない場合、結果は代わりにnull
になります。 -
sum()
- 数字のセットの合計を計算します。null 以外の値がない場合、結果は代わりにnull
になります。以下の表は、指定のフィールドに基づいて返されるタイプを示しています。
フィールドタイプ | 戻り値のタイプ |
---|---|
Integral (BigInteger 以外) | ロング |
Float または Double | Double |
BigInteger | BigInteger |
BigDecimal | BigDecimal |
11.3.5.8. グループ化および集計を使用したクエリーの評価
集計クエリーには、通常のクエリーのようにフィルター条件を含めることができます。フィルタリングは、グループ化操作の前後の 2 つのステージで実行できます。グループ化操作の実行前に groupBy()
メソッドを起動する前に定義されたフィルター条件はすべて、キャッシュエントリーに直接 (最終的なデプロイメントではなく) キャッシュエントリーに適用されます。これらのフィルター条件は、照会されたエンティティータイプの任意のフィールドを参照でき、グループ化ステージの入力となるデータセットを制限することを目的としています。groupBy()
メソッドの呼び出し後に定義されたフィルター条件はすべて、デプロイメントおよびグループ化操作の結果がデプロイメントされます。このフィルター条件は、groupBy()
フィールドまたは集約されたフィールドのいずれかを参照できます。select 句で指定されていない集約フィールドを参照することは許可されています。ただし、非集計フィールドと非グループ化フィールドを参照することは禁止されています。このフェーズでフィルタリングすると、プロパティーに基づいてグループの数が減ります。通常のクエリーと同様に、並べ替えも指定できます。順序付け操作は、グループ化操作後に実行され、groupBy()
フィールドまたは集約されたフィールドのいずれかを参照できます。
11.3.5.9. フルテキスト検索の使用
11.3.5.9.1. Fuzzy クエリー
ファジークエリー add ~
を整数とともに実行するには、用語の後に使用される用語からの距離を表します。たとえば、以下のようになります。
FROM sample_bank_account.Transaction WHERE description : 'cofee'~2
11.3.5.9.2. 範囲クエリー
以下の例に示すように、範囲クエリーを実行するには、中括弧のペア内で指定の境界を定義します。
FROM sample_bank_account.Transaction WHERE amount : [20 to 50]
11.3.5.9.3. フレーズクエリー
次の例に示すように、単語のグループは引用符で囲むことで検索できます。
FROM sample_bank_account.Transaction WHERE description : 'bus fare'
11.3.5.9.4. 近接クエリー
特定の距離内で 2 つの用語を検索して近接クエリーを実行するには、フレーズの後に距離とともに ~
を追加します。たとえば、以下の例では、キャンセル と fee という単語が 3 個以上ありません。
FROM sample_bank_account.Transaction WHERE description : 'canceling fee'~3
11.3.5.9.5. ワイルドカードクエリー
"text" または "test" を検索するには、単一文字のワイルドカード検索 ?
を使用します。
FROM sample_bank_account.Transaction where description : 'te?t'
"test"、"tests"、"tester を検索するには 、マルチ文字のワイルドカード検索 *
を使用します。
FROM sample_bank_account.Transaction where description : 'test*'
11.3.5.9.6. 正規表現クエリー
正規表現クエリーは、/
の間のパターンを指定することで実行できます。Ickle は Lucene の正規表現構文を使用しているため、単語 moat
または boat
を検索するには、以下を使用できます。
FROM sample_library.Book where title : /[mb]oat/
11.3.5.9.7. クエリーのブースト
用語は、指定のクエリーにおける耐障害性を高めるために ^
を追加し、条件を強化できます。たとえば、ビールとビールとの関連性が 3 倍高いビールとワインを含むタイトルを検索するには、次のように使用できます。
FROM sample_library.Book WHERE title : beer^3 OR wine