keyArgs (apollo)
from typePolicies (apollo)
引数込みで別キャッシュにするかどうかを指定する
docs
デフォルトの動作
引数が異なれば、別物としてキャッシュされる
e.g.
code:graphql
query {
books(category: "fiction") { id title }
}
上記のフィールドはbooks({"category": "fiction"}) というキーでキャッシュに保存される
指定方法
配列で指定する
指定された引数のみをキャッシュキーに含める
code:ts
keyArgs: "category", "sortOrder"
falseにする
引数をキーに含めない
つまり、任意の実引数に対して、同じモノとみなしてキャッシュする
e.g. paginationでよく使われる (merge (apollo)を併用)
関数を使う
args (実引数) と context (フィールド名やtypenameなど)に基づき、動的にキー生成ルールを変える
e.g.
code:ts
keyArgs(args, context) {
if (!args?.filter) return false; // 全引数を無視
if (args.filter.type === "popular") return "filter", "sort";
return "filter";
}
keyArgs (apollo)#690f616e00000000004de72a
具体例
前提として、popularはジャンル問わず全体での人気書籍一覧の取得をするものとする
code:ts
books: {
keyArgs(args, { fieldName }) {
// popular フラグが true のときは引数を無視して同じキャッシュキーを使う
if (args?.popular) return false;
// 通常は genre をキャッシュキーに含める
return "genre";
},
merge(existing = [], incoming) {
return ...existing, ...incoming;
}
}
books(genre: "fiction")
キャッシュキーは "books:{"genre":"fiction"}"
ジャンルごとにキャッシュされ、同じジャンルを再度フェッチした場合はキャッシュを使う
books(popular: true)
人気モードでは、ジャンル引数を無視して、全て同じキャッシュキー("books")にまとめる
全ジャンル横断で人気の本を一覧するという性質のものなので、ジャンルに依存しないため
もし、keyArgsをデフォルトのままにしていると下記のようにキャッシュが無駄に分かれてしまう
code:result(js)
ROOT_QUERY {
books({"popular":true}): Book:1, Book:2, Book:3
books({"popular":true,"genre":"fiction"}): Book:1, Book:2, Book:3 ← 重複!
books({"popular":true,"genre":"science"}): Book:1, Book:2, Book:3 ← 重複!
}
同じ結果が返ってくるのに、個別にキャッシュされてしまい、メモリ効率も悪く、キャッシュの一貫性も壊れる
#wip
gpt-5.icon
KeyArgsFunction の引数
args: Record<string, any> | null
GraphQL フィールドに渡された引数。例:
code:graphql
books(filter: { genre: "sci-fi" })
なら args は { filter: { genre: "sci-fi" } }。
context
次の情報が含まれます:
table:_
プロパティ 内容
typename 親オブジェクトの型名(例: "Query")
fieldName 現在のフィールド名(例: "books")
field 実際の FieldNode(ASTノード)。Directive情報なども参照可能
variables クエリで使われた変数(ある場合)
⚙️ 戻り値の意味
KeyArgsFunction の戻り値は次のいずれか:
table:_
戻り値 意味
string または KeySpecifier その配列要素をキーとして使う
false または null 全引数を無視(keyArgs: false と同等)
void デフォルト動作にフォールバック