検索およびアグリゲーションクエリの構築
@searchableディレクティブを@modelタイプに追加して、OpenSearchベースのデータ検索と結果アグリゲーションを有効化します。これにより、以下のことができます:
- 部分文字列マッチング、ワイルドカード、正規表現、
and/or/not条件などの高度なフィルタを使用してデータを検索する - 合計、平均、最小値、最大値、用語などのアグリゲーション値を取得する
- 検索結果の総数を取得する
- 1つまたは複数のフィールド全体で検索結果をソートする
type Student @model @searchable { name: String dateOfBirth: AWSDate email: AWSEmail examsCompleted: Int}
@searchableディレクティブが追加されると、モデルに追加されたすべての新しいレコードはOpenSearchにストリーミングされます。既存のデータをバックフィルするには、DynamoDBテーブルからOpenSearchインデックスをバックフィルするを参照してください。
データの検索とフィルター
@searchableディレクティブが付加されたすべてのモデルは、レコードを検索およびフィルターするための新しい「search」GraphQLクエリを生成します。上記の例では、「searchStudents」クエリを使用して「Student」レコードを検索できます。
filterパラメータを使用して、フィールド値に基づいてレコードをフィルターできます。
query SearchStudentsByEmail { searchStudents(filter: { name: { eq: "Rene Brandel" } }) { items { id name email } }}上記の例では、検索結果は「Rene Brandel」という名前の学生で構成されています。
サポートされている検索操作
| フィールドタイプ | サポートされている検索操作 |
|---|---|
| String | ne, eq, match, matchPhrase, matchPhrasePrefix, multiMatch, exists, wildcard, regexp |
| Int | ne, gt, lt, gte, lte, eq, range |
| Float | ne, gt, lt, gte, lte, eq, range |
| Boolean | eq, ne |
| Enum | ne, eq, match, matchPhrase, matchPhrasePrefix, multiMatch, exists, wildcard, regexp |
ネストされた検索条件(and、or、not)
フィルターパラメータを使用して、ネストされたand/or/not条件を渡します。
query MyQuery { searchStudents( filter: { name: { wildcard: "*Brandel" } or: [{ dateOfBirth: { lt: "2000-01-01" } }, { email: { exists: true } }] } ) { items { id name email dateOfBirth } }}デフォルトでは、フィルタープロパティ内のすべての操作はandされています。検索クエリのfilterパラメータでorまたはnotプロパティを使用して、この動作をオーバーライドしてください。
上記のクエリは、以下の条件を満たす「Student」を返します:
- 名前が「Brandel」で終わる
and- 生年月日が2000-01-01より前である
or- メールアドレスが存在する
検索結果のソート
sortパラメータを使用して、フィールドを昇順または降順で検索結果をソートします。field引数はモデルで利用可能なフィールドを受け付けます。directionはascまたはdescを受け付けます。
query SearchAndSort { searchStudents( filter: { name: { wildcard: "*Brandel" } } sort: { direction: desc, field: name } ) { items { name id } }}上記の例では、検索結果はdesc(降順)でnameに基づいてソートされています。
複数フィールドでの検索結果のソート
複数のフィールドでソートするには、ソート条件の配列を指定します。複数のフィールドでソートする場合、ソート条件はsort配列の順序で適用されます。
query SearchAndSort { searchStudents( filter: { name: { wildcard: "*Brandel" } } sort: [ { field: name, direction: desc } # ソート条件 #1 { field: dateOfBirth, direction: asc } # ソート条件 #2 ] ) { items { id name dateOfBirth } }}上記の例では、検索結果は最初にnameでdesc(降順)でソートされ、次にdateOfBirthでasc(昇順)でソートされます。
検索結果の改ページネーション
デフォルトでは、検索結果のページサイズは100です。ページサイズをカスタマイズするには、limitパラメータを変更します。nextTokenをクエリして、後続の改ページネーションリクエストで使用します:
query MyQuery { searchTodos(nextToken: "<YOUR_NEXT_TOKEN>") { # クエリにnextTokenを渡す items { description id name createdAt } nextToken # 改ページネーションのためのNextToken }}検索結果の合計数
クエリ応答にtotalフィールドを追加して、検索結果ヒットの総数を取得します。
query MyQuery { searchStudents(filter: { name: { wildcard: "*Brandel" } }) { items { id } total # 合計数を取得するために指定 }}上記の例では、応答のtotalフィールドに、名前が「Brandel」で終わる「Students」の検索結果の総数が含まれます。注:totalは改ページネーション設定に関わらず、すべてのレコードに基づいて計算されます。
検索結果のアグリゲーション値(最小値、最大値、平均値、合計、用語)
aggregatesパラメータを使用して、「最小値」、「最大値」、「平均値」、「合計」などのアグリゲーション値を取得し、aggregateItemsフィールドで返します。注:aggregatesは改ページネーション設定に関わらず、すべてのレコードに基づいて計算されます。
aggregate``typeとしてmin値を指定し、応答フィールドでaggregateItemsを指定します。
query MyQuery { searchStudents( aggregates: { type: min # 「min」値を取得することを指定 field: examsCompleted # アグリゲーション値のフィールドを指定 name: "minimumExams" # 応答フィールドで参照するための名前を指定 } filter: { name: { wildcard: "Rene*" } } ) { aggregateItems { name result { ... on SearchableAggregateScalarResult { value } } } }}上記の例では、応答に「Rene」で始まる名前を持つすべての学生の「examsCompleted」の最小値が含まれます。
{ "data": { "searchStudents": { "aggregateItems": [{ "name": "minimumExams", "result": { "value": 7 } }] } }}aggregate``typeとしてmax値を指定し、応答フィールドでaggregateItemsを指定します。
query MyQuery { searchStudents( aggregates: { type: max # 「max」値を取得することを指定 field: examsCompleted # アグリゲーション値のフィールドを指定 name: "maximumExams" # 応答フィールドで参照するための名前を指定 } filter: { name: { wildcard: "Rene*" } } ) { aggregateItems { name result { ... on SearchableAggregateScalarResult { value } } } }}上記の例では、応答に「Rene」で始まる名前を持つすべての学生の「examsCompleted」の最大値が含まれます。
{ "data": { "searchStudents": { "aggregateItems": [{ "name": "maximumExams", "result": { "value": 28 } }] } }}aggregate``typeとしてavg値を指定し、応答フィールドでaggregateItemsを指定します。
query MyQuery { searchStudents( aggregates: { type: avg # 「avg」値を取得することを指定 field: examsCompleted # アグリゲーション値のフィールドを指定 name: "averageExams" # 応答フィールドで参照するための名前を指定 } filter: { name: { wildcard: "Rene*" } } ) { aggregateItems { name result { ... on SearchableAggregateScalarResult { value } } } }}上記の例では、応答に「Rene」で始まる名前を持つすべての学生の「examsCompleted」の平均値が含まれます。
{ "data": { "searchStudents": { "aggregateItems": [{ "name": "averageExams", "result": { "value": 17.3 } }] } }}aggregate``typeとしてsum値を指定し、応答フィールドでaggregateItemsを指定します。
query MyQuery { searchStudents( aggregates: { type: sum # 「sum」値を取得することを指定 field: examsCompleted # アグリゲーション値のフィールドを指定 name: "examsSum" # 応答フィールドで参照するための名前を指定 } filter: { name: { wildcard: "Rene*" } } ) { aggregateItems { name result { ... on SearchableAggregateScalarResult { value } } } }}上記の例では、応答に「Rene」で始まる名前を持つすべての学生のすべての「examsCompleted」値の合計が含まれます。
{ "data": { "searchStudents": { "aggregateItems": [{ "name": "examsSum", "result": { "value": 392 } }] } }}aggregate``typeとしてterms値を指定し、応答フィールドでaggregateItemsを指定します。
query MyQuery { searchTodos( aggregates: { field: description, type: terms, name: "descriptionTerms" } ) { aggregateItems { result { ... on SearchableAggregateBucketResult { __typename buckets { doc_count key } } } name } }}上記の例では、応答に説明の用語とそのカウントが含まれます:
{ "data": { "searchTodos": { "aggregateItems": [ { "result": { "__typename": "SearchableAggregateBucketResult", "buckets": [{ "doc_count": 2, "key": "Shopping list" }, { "doc_count": 1, "key": "Me next todo" }] }, "name": "descriptionTerms" } ] } }}本番環境のOpenSearchをセットアップ
デフォルトでは、Amplify CLIはt2.smallインスタンスタイプを設定します。これはプロトタイピングを開始するのに適していますが、OpenSearchベストプラクティスによると本番環境での使用は推奨されていません。
環境ごとにOpenSearchインスタンスタイプを設定するには:
amplify env addを実行して新しい環境を作成します(例:「prod」)amplify/team-provider-info.jsonファイルを編集し、OpenSearchInstanceTypeをアプリケーションに適したインスタンスタイプに設定します
{ "dev": { "categories": { "api": { "<your-api-name>": { "OpenSearchInstanceType": "t2.small.elasticsearch" } } } }, "prod": { "categories": { "api": { "<your-api-name>": { "OpenSearchInstanceType": "t2.medium.elasticsearch" } } } }}amplify pushで変更をデプロイします
Amazon OpenSearchServiceインスタンスタイプの詳細については、こちらをご覧ください。
動作方法
@searchableディレクティブは@modelタイプのデータをAmazon OpenSearchServiceにストリーミングし、OpenSearchに対してクエリを実行するための検索リゾルバーを設定します。
@searchableディレクティブのタイプ定義:
# DynamoDBからOpenSearchにデータをストリーミングし、検索機能を公開します。directive @searchable(queries: SearchableQueryMap) on OBJECTinput SearchableQueryMap { search: String}