14.3. リモートクエリー

Java エンティティーのインデックス作成および埋め込みクライアントへの検索をサポートする以外に、Data Grid はリモート、言語に依存しないクエリーのサポートを導入しました。

この場合、2 つの主要な変更が必要でした。

  • JVM 以外のクライアントは Apache Lucene の Java API を直接使用することはできないため、Data Grid は、現在 Hot Rod クライアントを実装するすべての言語に簡単に実装できる内部 DSL に基づいて、独自の新しい クエリー言語 を定義します。
  • インデックスを有効にするために、クライアントによるキャッシュに配置されるエンティティーは、クライアントによってのみ認識される不透明なバイナリーブロブではなくなりました。これらの構造はサーバーとクライアントの両方に認識されるため、構造化データをエンコードする一般的な方法を使用する必要があります。さらに、マルチ言語クライアントがデータにアクセスできるようにするには、言語とプラットフォームに依存しないエンコーディングが必要です。Google の Protocol Buffers は、効率性、堅牢性、優れた複数言語のサポート、スキーマの進化のサポートにより、有線およびストレージの両方のエンコーディング形式として選択されました。

14.3.1. Protobuf でエンコードされたエンティティーの保存

保存されたエンティティーにインデックスを付けてクエリーできるリモートクライアントは、ProtoStream マーシャラーを使用して実行する必要があります。これは、検索機能が機能するための キー です。ただし、Protobuf エンティティーを保存して、プラットフォームの独立性の利点を得ることや、不要な場合にインデックスを有効にしないようにすることもできます。

14.3.2. Protobuf でエンコードされたエントリーのインデックス化

前のセクションで説明したようにクライアントを設定したら、サーバー側でキャッシュのインデックス設定を開始できます。インデックスとさまざまなインデックス固有の設定は組み込みモードと同じで、Data Grid のクエリー で説明されています。

ただし、追加の設定手順が必要になります。埋め込みモードでは、インデックス作成メタデータは、エントリーのクラス上のさまざまな Hibernate Search アノテーションの存在を分析することによって Java リフレクションを介して取得されますが、エントリーが protobuf エンコードされている場合、これは明らかに不可能です。サーバーは、クライアントと同じ記述子 (.proto ファイル) から関連するメタデータを取得する必要があります。記述子は '___protobuf_metadata' という名前のサーバーで専用キャッシュに保存されます。このキャッシュのキーと値はどちらもプレーンテキストの文字列です。したがって、新しいスキーマの登録は、スキーマ名をキーとして、スキーマファイル自体を値として使用して、このキャッシュに対して put 操作を実行するのと同じくらい簡単です。または、CLI (cache-container=*:register-proto-schemas() オペレーション経由)、管理コンソール、または JMX 経由の ProtobufMetadataManager MBean を使用することもできます。セキュリティーが有効になっている場合、リモートプロトコル経由でスキーマキャッシュにアクセスするには、ユーザーが '___schema_manager' ロールに属している必要があります。

注記

キャッシュのインデックス作成が有効になっている場合でも、インデックスを作成する必要があるフィールドを指定するために @Indexed および @Field の protobuf スキーマドキュメントアノテーションを使用しない限り、Protobuf でエンコードされたエントリーのフィールドにはインデックスが作成されません。

14.3.3. リモートクエリーの例

この例では、LibraryInitializerImpl の例を利用するようにクライアントを設定し、いくつかのデータをキャッシュに配置し、検索する方法を示します。以下の例では、必要な .proto ファイルを ___protobuf_metadata キャッシュに登録することで、インデックスが有効になっている ことを前提としています。

ConfigurationBuilder clientBuilder = new ConfigurationBuilder();
clientBuilder.addServer()
    .host("10.1.2.3").port(11234)
    .addContextInitializers(new LibraryInitializerImpl());

RemoteCacheManager remoteCacheManager = new RemoteCacheManager(clientBuilder.build());

Book book1 = new Book();
book1.setTitle("Infinispan in Action");
remoteCache.put(1, book1);

Book book2 = new Book();
book2.setTile("Hibernate Search in Action");
remoteCache.put(2, book2);

QueryFactory qf = Search.getQueryFactory(remoteCache);
Query query = qf.from(Book.class)
            .having("title").like("%Hibernate Search%")
            .build();

List<Book> list = query.list(); // Voila! We have our book back from the cache!

クエリ作成で重要なのは、org.infinispan.client.hotrod.Search.getQueryFactory() メソッドを使用してリモートキャッシュ用の QueryFactory を取得することです。これ以降、クエリーの作成は、この セクションで説明する埋め込みモードと似ています。

14.3.4. 分析

分析は、入力データを、インデックスを作成してクエリーできる 1 つ以上の用語に変換するプロセスです。

14.3.4.1. デフォルトのアナライザー

Data Grid は、以下のようにデフォルトのアナライザーのセットを提供します。

定義説明

standard

テキストフィールドをトークンに分割し、空白と句読点を区切り文字として扱います。

simple

非文字で区切り、すべての文字を小文字に変換することにより、入力ストリームをトークン化します。空白と非文字は破棄されます。

whitespace

テキストストリームを空白で分割し、空白以外の文字のシーケンスをトークンとして返します。

キーワード

テキストフィールド全体を単一トークンとして扱います。

stemmer

SnowballPorter フィルターを使用して英語の単語を語幹にします。

ngram

デフォルトでサイズ 3 つのグラムである n-gram トークンを生成します。

filename

テキストフィールドを standard アナライザーよりも大きなサイズトークンに分割し、空白文字を区切り文字として扱い、すべての文字を小文字に変換します。

これらのアナライザー定義は Apache Lucene をベースとし、as-is で提供されます。tokenizers、filters、および CharFilters に関する詳細は、適切な Lucene のドキュメントを参照してください。

14.3.4.2. アナライザー定義の使用

アナライザー定義を使用するには、.proto スキーマファイルで名前でそれらを参照します。

  1. Analyze.YES 属性を追加して、プロパティーが分析されていることを示します。
  2. @Analyzer アノテーションで アナライザー定義を指定します。

以下は、参照されたアナライザー定義の例になります。

/* @Indexed */
message TestEntity {

    /* @Field(store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "keyword")) */
    optional string id = 1;

    /* @Field(store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "simple")) */
    optional string name = 2;
}

14.3.4.3. カスタムアナライザー定義の作成

カスタムアナライザー定義が必要な場合は、以下を行います。

  1. JAR ファイルにパッケージ化された ProgrammaticSearchMappingProvider インターフェイスの実装を作成します。
  2. JARMETA-INF/services/ ディレクトリーに org.infinispan.query.spi.ProgrammaticSearchMappingProvider という名前のファイルを指定します。このファイルには、実装の完全修飾クラス名が含まれている必要があります。
  3. JAR を Data Grid インストールの standalone/deployments ディレクトリーにコピーします。

    重要

    起動中に Data Grid サーバーでデプロイメントが利用可能である必要があります。サーバーがすでに実行中の場合は、デプロイメントを追加できません。

    以下は、ProgrammaticSearchMappingProvider インターフェイスの実装例です。

    import org.apache.lucene.analysis.core.LowerCaseFilterFactory;
    import org.apache.lucene.analysis.core.StopFilterFactory;
    import org.apache.lucene.analysis.standard.StandardFilterFactory;
    import org.apache.lucene.analysis.standard.StandardTokenizerFactory;
    import org.hibernate.search.cfg.SearchMapping;
    import org.infinispan.Cache;
    import org.infinispan.query.spi.ProgrammaticSearchMappingProvider;
    
    public final class MyAnalyzerProvider implements ProgrammaticSearchMappingProvider {
    
       @Override
       public void defineMappings(Cache cache, SearchMapping searchMapping) {
          searchMapping
                .analyzerDef("standard-with-stop", StandardTokenizerFactory.class)
                   .filter(StandardFilterFactory.class)
                   .filter(LowerCaseFilterFactory.class)
                   .filter(StopFilterFactory.class);
       }
    }
  4. 以下のように、キャッシュコンテナー設定で JAR を指定します。

    <cache-container name="mycache" default-cache="default">
       <modules>
         <module name="deployment.analyzers.jar"/>
       </modules>
    ...