Elasticsearch オペレーション

Spring Data Elasticsearch は、Elasticsearch インデックスに対して呼び出すことができる操作を定義するためにいくつかのインターフェースを使用します (リアクティブインターフェースの説明については、リアクティブ型 Elasticsearch オペレーションを参照してください)。

これらのインターフェースは、Elasticsearch API (英語) の構造に対応します。

インターフェースのデフォルト実装は以下を提供します。

  • インデックス管理機能。

  • ドメイン型の読み取り / 書き込みマッピングのサポート。

  • 豊富なクエリと条件 API。

  • リソース管理と例外の変換。

インデックス管理、インデックスとマッピングの自動作成。

IndexOperations インターフェースと、ElasticsearchOperations インスタンスから取得できる実装 (たとえば、operations.indexOps(clazz) の呼び出しを使用) により、ユーザーはインデックスを作成したり、マッピングを配置したり、テンプレートとエイリアス情報を Elasticsearch クラスターに格納したりできます。作成されるインデックスの詳細は、@Setting アノテーションを使用して設定できます。詳細については、インデックス設定を参照してください。

IndexOperations または ElasticsearchOperations の実装によるこれらの操作はいずれも自動的には行われません。メソッドを呼び出すのはユーザーの責任です。

Spring Data Elasticsearch リポジトリを使用する場合、インデックスの自動作成とマッピングの書き込みがサポートされています。対応するマッピングを使用したインデックスの自動作成を参照してください。

使用例

この例では、挿入された ElasticsearchOperations インスタンスを Spring REST コントローラーで使用する方法を示します。この例では、Person が @Document@Id などのアノテーションが付けられたクラスであると想定しています ( マッピングアノテーションの概要を参照)。

例 1: ElasticsearchOperations の使い方
@RestController
@RequestMapping("/")
public class TestController {

  private  ElasticsearchOperations elasticsearchOperations;

  public TestController(ElasticsearchOperations elasticsearchOperations) { (1)
    this.elasticsearchOperations = elasticsearchOperations;
  }

  @PostMapping("/person")
  public String save(@RequestBody Person person) {                         (2)
    Person savedEntity = elasticsearchOperations.save(person);
    return savedEntity.getId();
  }

  @GetMapping("/person/{id}")
  public Person findById(@PathVariable("id")  Long id) {                   (3)
    Person person = elasticsearchOperations.get(id.toString(), Person.class);
    return person;
  }
}
1Spring が、提供された ElasticsearchOperations Bean をコンストラクターに挿入します。
2Elasticsearch クラスターにいくつかのエンティティを保存します。ID は返されたエンティティから読み取られます。これは、person オブジェクトでは null であり、Elasticsearch によって作成された可能性があるからです。
3ID による取得を使用してエンティティを取得します。

ElasticsearchOperations の可能性をすべて確認するには、API ドキュメントを参照してください。

検索結果の種類

DocumentOperations インターフェースのメソッドを使用してドキュメントを取得すると、見つかったエンティティのみが返されます。SearchOperations インターフェースのメソッドを使用して検索する場合、見つかったエンティティのスコアsortValues など、各エンティティの追加情報が利用できます。

この情報を返すために、各エンティティは、このエンティティ固有の追加情報を含む SearchHit オブジェクトにラップされます。これらの SearchHit オブジェクト自体は、maxScore やリクエストされた集計、またはリクエストを完了するのにかかった実行時間などの検索全体に関する情報も含む SearchHits オブジェクト内で返されます。現在、次のクラスとインターフェースが利用可能です。

検索ヒット <T>

次の情報が含まれます。

  • ID

  • スコア

  • 値の並べ替え

  • 強調表示フィールド

  • インナーヒット (これは、最終的に返される内部ヒットを含む埋め込み SearchHits オブジェクトです。)

  • 型 <T> の取得されたエンティティ

検索ヒット <T>

次の情報が含まれます。

  • 総ヒット数

  • 総ヒット数関係

  • 最大スコア

  • SearchHit<T> オブジェクトのリスト

  • 返された集計

  • 返された提案結果

検索ページ <T>

SearchHits<T> 要素を含み、リポジトリメソッドを使用したページングアクセスに使用できる Spring Data Page を定義します。

SearchScrollHits<T>

ElasticsearchRestTemplate の低レベルスクロール API 関数によって返され、Elasticsearch スクロール ID で SearchHits<T> を強化します。

SearchHitsIterator<T>

SearchOperations インターフェースのストリーミング関数によって返されるイテレーター。

ReactiveSearchHits

ReactiveSearchOperations には Mono<ReactiveSearchHits<T>> を返すメソッドがあり、これには SearchHits<T> オブジェクトと同じ情報が含まれますが、含まれる SearchHit<T> オブジェクトはリストとしてではなく Flux<SearchHit<T>> として提供されます。

照会

SearchOperations および ReactiveSearchOperations インターフェースで定義されているメソッドのほとんどすべては、検索のために実行するクエリを定義する Query パラメーターを取ります。Query はインターフェースであり、Spring Data と Elasticsearch は 3 つの実装 (CriteriaQueryStringQueryNativeQuery) を提供します。

CriteriaQuery

CriteriaQuery ベースのクエリを使用すると、Elasticsearch クエリの構文や基本を知らなくても、データを検索するクエリを作成できます。ユーザーは、検索対象のドキュメントが満たす必要のある条件を指定する Criteria オブジェクトを単純に連鎖して組み合わせるだけで、クエリを構築できます。

AND または OR について話すとき、条件を組み合わせる際に、Elasticsearch では AND は必須条件に変換され、OR は推奨条件に変換されることに留意してください。

Criteria とその使用箇所は、例によって最もよく説明されます (price プロパティを持つ Book エンティティがあると仮定しましょう)。

例 2: 指定した価格で本を入手する
Criteria criteria = new Criteria("price").is(42.0);
Query query = new CriteriaQuery(criteria);

同じフィールドの条件は連鎖させることができ、論理 AND で結合されます。

例 3: 指定した価格で本を入手する
Criteria criteria = new Criteria("price").greaterThan(42.0).lessThan(34.0);
Query query = new CriteriaQuery(criteria);

Criteria をチェーンする場合、デフォルトでは AND ロジックが使用されます。

例 4: 名が James で姓が Miller であるすべての人物を取得します。
Criteria criteria = new Criteria("lastname").is("Miller") (1)
  .and("firstname").is("James")                           (2)
Query query = new CriteriaQuery(criteria);
1 最初の Criteria
2and() は新しい Criteria を作成し、それを最初の Criteria にチェーンします。

ネストされたクエリを作成する場合は、サブクエリを使用する必要があります。Miller という姓と Jack または John という名前を持つすべての人物を検索したいと仮定します。

例 5: ネストされたサブクエリ
Criteria miller = new Criteria("lastName").is("Miller")  (1)
  .subCriteria(                                          (2)
    new Criteria().or("firstName").is("John")            (3)
      .or("firstName").is("Jack")                        (4)
  );
Query query = new CriteriaQuery(criteria);
1 姓に対して最初の Criteria を作成する
2 これを AND で subCriteria に組み合わせる
3 このサブ条件は、名 John の OR の組み合わせです。
4 そして名前はジャックです

利用可能なさまざまな操作の完全な概要については、Criteria クラスの API ドキュメントを参照してください。

StringQuery

このクラスは、Elasticsearch クエリを JSON 文字列として受け取ります。次のコードは、名前が "Jack" である人物を検索するクエリを示しています。

Query query = new StringQuery("{ \"match\": { \"firstname\": { \"query\": \"Jack\" } } } ");
SearchHits<Person> searchHits = operations.search(query, Person.class);

すでに Elasticsearch クエリを使用している場合は、StringQuery を使用するのが適切です。

NativeQuery

NativeQuery は、クエリを構築して集約を使用する場合など、複雑なクエリや、Criteria API を使用して表現できないクエリがある場合に使用するクラスです。これにより、Elasticsearch ライブラリのさまざまな co.elastic.clients.elasticsearch._types.query_dsl.Query 実装をすべて使用できるため、「ネイティブ」という名前が付けられています。

次のコードは、特定の firstName を持つ人物を検索し、見つかったドキュメントについて、これらの人物の lastName の出現数をカウントする用語集計を行う方法を示しています。

Query query = NativeQuery.builder()
	.withAggregation("lastNames", Aggregation.of(a -> a
		.terms(ta -> ta.field("lastName").size(10))))
	.withQuery(q -> q
		.match(m -> m
			.field("firstName")
			.query(firstName)
		)
	)
	.withPageable(pageable)
	.build();

SearchHits<Person> searchHits = operations.search(query, Person.class);

SearchTemplateQuery

これは、格納された検索テンプレートと組み合わせて使用される Query インターフェースの特別な実装です。詳細については、検索テンプレートのサポートを参照してください。