データの追加
楽観的更新(optimistic updates)により、高速でレスポンスの良いユーザー体験を実現します。
Mutations を使用する理由
データベース内に新しいレコードを作成したり、既存のレコードを更新したりする必要があります。Squid Client SDK は insert と update の操作を提供しており、クライアント側で変更を楽観的に適用して UI に即時フィードバックを返し、その後サーバーと非同期に同期します。
クイックスタート
// Insert a new document
await squid.collection<User>('users').doc('user_1').insert({
name: 'Alice',
email: 'alice@example.com',
});
概要
transaction 内で実行されている場合を除き、すべての insert と update は Promise を返し、サーバー上で mutation が適用されると解決(resolve)します。
insert と update はローカルで楽観的に適用され、クライアント上に即座に反映されます。その後、整合性がありクリーンなデータ状態を確保するために、変更がサーバーへ非同期に送信されます。
書き込み mutation には insert、update、setInPath の 3 種類があります。いずれも document reference に対して実行します。
コアコンセプト
Insert
Insert は新しい document を作成するために使用します。
collection に新しい document を insert するには、DocumentReference に対して insert メソッドを呼び出し、
引数として新しい document データを渡します。
try {
await squid.collection<User>('users').doc('new_user_id').insert({
name: 'John Doe',
email: 'johndoe@example.com',
});
console.log('User added successfully');
} catch (error) {
console.error(`Failed to add user ${error}`);
}
バックエンドの security rules により、各 mutation を誰が実行できるかを粒度細かく制御できます。これらのルールは MutationContext をパラメータとして受け取り、変更前後の document のスナップショットを含む、mutation に関する必要な情報がすべて入っています。security rules の詳細を読み、書き方を理解してください。
Insert many
insertMany メソッドは、複数の document を一度に効率よく insert および/または update するために使用します。次の例では、新しいユーザー document の配列を追加します。
const newDocuments = [
{
id: 'new_user_id1',
data: {
name: 'John Doe',
email: 'johndoe@example.com',
},
},
{
id: 'new_user_id2',
data: {
name: 'Jan Smith',
email: 'jansmith@example.com',
},
},
];
try {
await squid.collection<User>('users').insertMany(newDocuments);
console.log('Users added successfully');
} catch (error) {
console.error(`Failed to add users ${error}`);
}
Update
document を update するには、DocumentReference に対して update メソッドを呼び出し、
部分更新データを含むオブジェクトを引数として渡します。
try {
await squid
.collection<User>('users')
.doc('existing_user_id')
.update({ email: 'new_email@example.com' });
console.log('User updated successfully');
} catch (error) {
console.error(`Failed to update user ${error}`);
}
Set in Path
DocumentReference に対して setInPath メソッドを呼び出し、プロパティへの path と新しい値を引数として渡すことで、document の特定のプロパティだけを update することもできます。path にはドット記法を使ってネストされたプロパティを指定します。
const userRef = squid.collection<User>('users').doc('existing_user_id');
try {
await userRef.setInPath('address.street', 'Main');
console.log('Updated successfully');
} catch (error) {
console.error(`Failed to update user ${error}`);
}
エラーハンドリング
| Error | Cause | Solution |
|---|---|---|
| Security rule rejection | mutation が security rules によりブロックされた | ユーザーがその collection に対する書き込み権限を持つことを確認する |
| Document already exists | 一部の connector type で、すでに存在する document ID に対して insert を呼び出した | 既存 document には update を使う、または一意の ID を使用する |
| Invalid data shape | insert したデータが collection schema に一致しない | データオブジェクトが期待される schema と型に一致することを確認する |
| Network error | mutation の確認のためにサーバーへ到達できなかった | 楽観的更新はロールバックされるため、操作をリトライする |
ベストプラクティス
-
部分的な変更には
update()を使用する:document 全体を再 insert するのではなく、変更されたフィールドのみを送信します。 -
深いネストの更新には
setInPath()を使用する:document の他の部分に触れずに、ネストされた単一フィールドだけを変更できます。Client code// Update only the city without affecting other address fields
await userRef.setInPath('address.city', 'New York'); -
バルク操作には
insertMany()を使用する:サーバーとの往復回数(round trips)を減らします。 -
複数 document にまたがる原子性(atomicity)が必要な場合は、関連する mutation を transaction でラップする。
-
mutation のエラーを処理する:クライアント側のバリデーションを通っても、security rules や schema チェックでサーバー側が変更を拒否する場合があります。