[AWS Amplify API] createdAtでソートした結果を返す

AWS Amplify,IT記事

AWS AmplifyのGraphQLで型を定義する。

その時、1つ目のテーブルを作るとする。ここではTodo型を作った。

type Todo
  @model
 {
  id: ID!
  title: String!
  createdAt: AWSDateTime
}

ここから

・list クエリで取得したとき、"createdAt"でソートされていてほしい。

・get で idを指定した取得もできるようにしたい。GetTodo($id: ID!)

その場合下記のようにする。

type Todo
  @model
  @key(
    name: "byTypeCreatedAt"
    fields: ["type", "createdAt"]
    queryField: "byCreatedAt"
  ) {
  id: ID!
  type: String!
  title: String!
  createdAt: AWSDateTime! 
}

・@keyで新しいインデックスとクエリを作っている。(fieldsに、新しく作ったtypeというフィールドとcreatedAtフィールドを指定。queryFiledを設定することでbyCreatedAtクエリが作られる。)

・新しく増えたtypeというフィールドには常に同じ値(例えば"t"とか"post"とかなんでも)を入れる。つまりTodoを作る時、以下のようにする。

 // 作成
 const res = await API.graphql({
      query: createTodo,
      variables: {
        input: {
          type: "b", // 同じ値を入れる
          title: this.form.title
        },
      },
    });

・そして作ったクエリ、ここではbyCreatedAtクエリをかければcreatedAtでソートされた結果が返ってくる。

        const res = await API.graphql({
          query: byCreatedAt,
          variables: { type: "b", sortDirection: "DESC" },
        }); // これは降順を指定した場合

これでcreatedAtでソートしたリストを得ることが出来た。

つまるところ、項目の一つを同じ値で埋めて@keyの仕様を回避するわけで、これはいいのか首をかしげたくなるが、DynamoDBの仕様上しかたなさそう。なるべく少ない文字列にしておこう。

@auto

・あと今は@keyのfieldsにはnon nullなフィールドしか指定できない。なのでcreatedAtには!をつける必要がある。上記でも以下のようになっている。

...
  createdAt: AWSDateTime! 
}

この部分は今後のAmplifyのアップデートで変わるそうだ。一度null可能にしたがバグが出たので戻ったりしたらしい。今後のアップデートでnull可能か指定できるようになるらしい。

・non nullになったcreatedAtは作るとき必ず値を設定しなければならない。なのでTodoを作るときcreatedAtも設定する必要がある。

・しかしそうなるとユーザーが好きに設定できてしまうのでサーバー側で設定してほしい。

・実現するにはリクエストマッピングテンプレートを設定する。面倒だ。

そんなところへ、自動で値を入れてくれる@autoカスタムディレクションを公開してくれている人がいる。使わせてもらおう!

https://github.com/hirochachacha/graphql-auto-transformer

リンク先の説明どおりに設定する。

npm install graphql-auto-transformer -D
{
    "Version": 5,
    "ElasticsearchWarning": true,
    "transformers": [
        "graphql-auto-transformer"
    ]
}
type Todo
  @model
  @key(
    name: "byTypeCreatedAt"
    fields: ["type", "createdAt"]
    queryField: "byCreatedAt"
  ) {
  id: ID!
  type: String!
  title: String!
  createdAt: AWSDateTime! @auto
}

Todo型は最終的に上記のようになった。

まとめ

正直ソートしたいだけなのにここまで妙に複雑だ。たぶんDynamoDBのせい。

amplifyは更新が速く(バグも多く)更新で記述が変わる。上記の方法も古くなると思われる。

しかしこのあたりのこと公式ドキュメントには書いておいてほしい。ハンズオン資料には書いてあるのでハンズオン資料も読もう。