全文検索機能: Back-end

AWS Amplifyを利用した全文検索機能の実装は非常にシンプルです。

@searchable

@searchableディレクティブを使用すると、該当のモデルを対象とした全文検索が可能になります。 ./amplify/backend/api/BoyakiGql/schema.graphqlを開き、編集します。

type Post
  @model (
    mutations: {create: "createPost", delete: "deletePost", update: null}
    timestamps: null
    subscriptions: { level: public}
  )
  @auth(rules: [
    {allow: owner, ownerField:"owner", provider: userPools, operations:[read, create, delete]}
    {allow: private, provider: userPools, operations:[read]}
    {allow: private, provider: iam ,operations:[create]}
  ])
  @key(name: "SortByTimestamp", fields:["type", "timestamp"], queryField: "listPostsSortedByTimestamp")
  @key(name: "BySpecificOwner", fields:["owner", "timestamp"], queryField: "listPostsBySpecificOwner")
  @searchable
{
  type: String! # always set to 'post'. used in the SortByTimestamp GSI
  id: ID
  content: String!
  owner: String
  timestamp: Int!
}

現在のschema.graphqlは以下のようになっています。

@searchableディレクティブを使用すると、Amazon DynamoDB StreamsAmazon Elasticsearch Serviceがプロビジョニングされます。 該当のDynamoDB TableにInsertされたデータをDynamoDB Streamsがフックし、Elasticsearchへレコードを追加します。 フロントエンドからElasticsearchにクエリを投げるには、GraphQL APIにセットアップされるsearchPostsというQueryを実行します。 @searchableディレクティブが付与される前にInsertされたデータに関してはElasticsearchでクエリできませんのでご注意ください。 @searchableの詳細はこちら

動作検証

残念ながら現在、@searchableはAmplify Mockingに対応しておりません。 そのため、今回はAWS AppSyncのマネジメントコンソールを用いて動作検証を行います。

クラウドへの変更反映

$ amplify push

実行には10分程度かかります。

Postの作成

@searchableディレクティブが付与される前にInsertされたデータに関してはElasticsearchでクエリできないため、あらたにPostを作成しておきます。

  1. $ amplify statusコマンドを実行し、Amplify hosting urlsの項目を確認してURLを確認します
  2. 作成したアプリを通じて、いくつかPostを作成しておきます(後ほど検索することを考えて、投稿内容を頭に残しておきましょう)

AWS AppSync

  1. AWS AppSyncのマネジメントコンソールを開きます。
  2. 今回作成したAPIを開きます(手順通り作成した場合はBoyakiGql-productionという名前)
  3. 左のメニューからクエリを開きます
  4. ▶︎アイコンの右側にある、ユーザープールでログインをクリックします
  5. ログインしたいユーザーのUsername/PasswordとWebClient IDを入力します
  6. WebClientIDは、./src/aws-exports.js内のaws_user_pools_web_client_idの項目を参照します
  7. 例: "aws_user_pools_web_client_id": "XXXXXXXXXXXxXXXXXXXXXXXXX"のXXXXXX…の部分
  8. 左側のペインに次のQueryを書き込みます。Amplifyの部分には検索したいフレーズを入力しましょう
query MyQuery{
  searchPosts (
      filter: {content: { matchPhrase: "AWS Amplify"} }
  ){
      items{
          id
          content
          owner
      }
  }
}
  1. contentに入力したフレーズが含まれるPost一覧が取得できれば成功です

matchPhraseはElasticsearchのmatch_phraseクエリに相当します。 半角スペース区切りで渡した検索キーワードが全てその順番に登場する場合にマッチします。 その他、matchmultiPhrasewildcardの使用や、or``and条件を利用した複雑なクエリも可能です。 @searchableで使用可能なクエリはこちらをご参照ください。