Amplifyのschemaに指定する@keyとは何なのか、なぜ使う必要があるのかについてまとめましたので、これをみていただければ@keyをどう活用するのかを理解いただけるはずです。
@keyをなぜ使うのか
DynamoDBのクエリは、最大で二つのAttribute(AppSyncのフィールド)を使うのがよいとされている。
この二つのAttributeはPartition Key(PK)とSort Key(SK)と呼ばれる。
DynamoDBはPK単体、またはPKとSKを組み合わせてプライマリキーとして利用することができる。
だから、これら2つのキーを使用する。
でもなぜPKとSKを使う必要があるのか?
使うことによって、効率を上げ、時間と通信コストを削減することができる。
使わずにクエリを書く場合、DynamoDBのTableの中身全てをスキャンすることになり、非常に効率が悪い。
この2つのキーを指定することが@keyの主な役割なのである!
データをランダムにしかフェッチ(取得)できない場合に、@keyを使用することでDynamoDBのインデックスを作成し、クエリを作成することができるんです。
AppSyncでは、 idが空の場合、 自動的にidを生成してidフィールドを埋めるが、入力を必須にするとクライアント側で渡す必要があり、自動生成機能を使えなくなってしまう。
実例
@key(name: "SortByTimestamp", fields:["type", "timestamp"], queryField: "listPostsSortedByTimestamp")
@key(name: "BySpecificOwner", fields:["owner", "timestamp"], queryField: "listPostsBySpecificOwner")
- nameとは: DynamoDBのインデックス(Global Secondary Index)の名前
- fieldsとは: 一つ目がPartition Keyに利用するフィールド、二つ目がSort Keyに利用するフィールド
ひとつだけ書くと、Partition Keyのみがセットアップされる。 - queryFieldとは:
getPost
のような、GraphQLのqueryの名前
上記2行はどのような働きをしているのか
listPostsSortedByTimestamp
・type
フィールドをPKにすることで、全てのPostをフェッチすることができる。
・timestamp
をSortKeyにすることで、timestamp
での昇降順ソートが可能になる。
listPostsBySpecificOwner
・PKにowner
を指定することで、あるowner
のPostをリストアップすることができる。
結論
@keyは、通信にかかる時間とコストを削減するために使用し、ソートのやリストアップの働きをする。
追記:GraphQL v2
2021年11月に、GraphQLのバージョンアップがあり、この@keyの記述方法が大きく変更となったので変更内容をまとめました。
AWSより出されているドキュメントはこちら
以下の例を元に、v2に置き換えてみましょう!
type Post @model
@key(name: "byUsername", fields: ["username"], queryField: "postsByUsername")
@auth(rules: [
{ allow: owner, ownerField: "username" },
{ allow: public, operations: [read] }
]) {
id: ID!
title: String!
content: String!
username: String
}
上記は、バージョン変更前のレガシーな書き方です。
これをv2で書くと、、
type Post
@model
@auth(
rules: [
{ allow: owner, ownerField: "username" }
{ allow: public, operations: [read] }
]
) {
id: ID!
title: String!
content: String!
username: String @index(name: "byUsername", queryField: "postsByUsername")
}
indexを指定したいカラムのところに記述します。
ここで指定するnameは、使われるわけではないですが、nameを指定することでindexの扱いとなります。
これにより、以下のクエリが生成されます。
export const postsByUsername = /* GraphQL */ `
query PostsByUsername(
$username: String
$sortDirection: ModelSortDirection
$filter: ModelPostFilterInput
$limit: Int
$nextToken: String
) {
postsByUsername(
username: $username
sortDirection: $sortDirection
filter: $filter
limit: $limit
nextToken: $nextToken
) {
items {
id
title
content
username
coverImage
createdAt
updatedAt
}
nextToken
}
}
`;
これで、バージョン変更前と同じクエリを作ることができました。
以上、お読みいただきありがとうございました。
コメント