追記(2021/12/11)—–
Amplifyの更新によりGraphQL Transformerはv2になり記述が大きく変わりました。以下のリンクを参考にしてください。
https://docs.amplify.aws/guides/api-graphql/query-with-sorting/q/platform/js/#overview
この記事も前のバージョンのやり方として残しておきます。
—–
AWS AmplifyのGraphQLで1つ目のテーブルを作るとする。例えばTodo型なら以下のようになる。
type Todo
@model
{
id: ID!
title: String!
createdAt: AWSDateTime
}
ここから
・list クエリで取得したとき、”createdAt”でソートされていてほしい。
・get で idを指定した取得もできるようにしたい。
その場合下記のようにする。
type Todo
@model
@key(
name: "byTypeCreatedAt"
fields: ["type", "createdAt"]
queryField: "byCreatedAt"
) {
id: ID!
type: String!
title: String!
createdAt: AWSDateTime!
}
・typeというフィールドを追加
・@keyで新しいインデックスとクエリを作っている。(プロパティのfieldsに、typeとcreatedAtフィールドを指定。queryFiledに設定することでbyCreatedAtという名前のクエリが作られる。)
・新しく増えたtypeというフィールドには常に同じ値(例えば”t”とか”post”とか)を入れる。つまりTodoを作る時、以下のようにする。
// 作成
const res = await API.graphql({
query: createTodo,
variables: {
input: {
type: "t", // 同じ値を入れる
title: this.form.title
},
},
});
そして@keyによりbyCreatedAtクエリが自動生成されているので、そのクエリを使えばcreatedAtでソートされた結果が返ってくる。
const res = await API.graphql({
query: byCreatedAt,
variables: { type: "t", 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"
]
}
あとAmplify Consoleでビルドする場合、ビルドコマンドに以下を追記する必要がある。
version: 1
backend:
phases:
build:
commands:
- npm install -g graphql-auto-transformer
- '# Execute Amplify CLI with the helper script'
- amplifyPush --simple
@autoを使うことでTodo型は最終的に以下のようになった。
type Todo
@model
@key(
name: "byTypeCreatedAt"
fields: ["type", "createdAt"]
queryField: "byCreatedAt"
) {
id: ID!
type: String!
title: String!
createdAt: AWSDateTime! @auto
}
まとめ
正直ソートしたいだけなのに妙に複雑だ。たぶんDynamoDBのせい。
amplifyは更新が速く(バグも多く)更新で記述が変わる。上記の方法も古くなると思われる。
このあたりのこと公式ドキュメントのガイドページ。またはハンズオン資料、またはissueに書いてある。