【GraphQL】複数のフィールドを組み合せがユニークなtypeのApollo cacheについて検証した【Tip!】
apollo clientはデフォルトでtypename:idをキャッシュIDとして対応付ける形で、キャッシュを保存しますが、
By default, an object's cache ID is the concatenation of the object's
__typename and id (or _id) fields, separated by a colon (:).
type Student {
class: string!
number: int!
name: string!
}
上記スキーマを確認すると、idフィールドが存在しないので、
通常とは違い、
typename:idをキャッシュIDとして、キャッシュを保存ができません。
そのため、apolloで個々のstudentをキャッシュするために以下のように設定を行うことができます。
結論
classとnumber(出席)の組み合わせはuniqueとなるので、
classとnumberをもとにキャッシュIDを構成する方針を取ります。
※uniqueの例
学校で青組の出席番号1の生徒は唯一。
class:青組 number:1
class:赤組 number:1
DynamoDBだとclassがPKで、numberがSKで、プライマリーキーが構成されているようなイメージ。
具体的には
アポロクライアント生成時に、keyFieldオプションに、classとnumberを指定して完了です。
const client = new ApolloClient({
uri: "apiエンドポイント",
cache: new InMemoryCache({
typePolicies: {
Student: {
keyFields: ["class", "number"],
},
Query: {
試しにStudentを取得するクエリを叩いて、InMemoryCacheを確認すると
Student:{"class":"赤組","number":"1"} : {__typename:'Student',
省略
Student:{"class":"赤組","number":"1"} がキャッシュID(文字列)として、キャッシュが保存されていることがわかります。
自身が持つフィールド(他のtypeのオブジェクト)が持つフィールドを、キャッシュIDとして使いたいパターンの場合
type Partner {
partnerA : User!
partnerB : User!
}
type User {
id: ID!
name: String!
}
PartnerのpartnerAフィールドのidフィールド と
PartnerのpartnerBフィールドのidフィールド をキャッシュIDとして構成したいケース。
この場合は以下のようにInMemoryCacheを設定します。
cache: new InMemoryCache({
typePolicies: {
Partner: {
keyFields: ["partnerA", ["id"], "partnerB", ["id"]],
},
[]の一個前のフィールドの中に定義されている、[]の中のフィールドをキャッシュIDに使います。
上記の例だと
partnerAフィールドのid と partnerBのidフィールドを、 type PartnerのキャッシュIDとして使用することとなります。
実際に以下のように保存されています。
//Partner:{"partnerA":{"id":"1"},"partnerB":{"id":"3"}}がキー
Partner:{"partnerA":{"id":"1"},"partnerB":{"id":"3"}} : 値
所感
graphQL apiを作成する際に、
なかなかidがないtypeを見かける機会がありませんでしたが、
dynamoDBを使用したときに、idがtypeに含まれていないケースに遭遇したので、
今回の記事を作成しました。
参考になれば幸いです。
Discussion
LGTM