[2020/10 更新]
writeFields
に関しては現在削除され使用不可能になっており、代わりにMapDiff
を使う必要があります。
詳しくはCloud Firestoreのセキュリティルールにかつて存在したwriteFields
を覚えていますか?を御覧ください
Cloud Firestoreのrulsを書く上でややこしい
-
resource
変数 -
request.resource
変数 -
writeFields
変数
のそれぞれの違いを説明しようと思います。これを見ればもう間違えることはなくなるはず。
TL;DR
-
resource
: 現在DBに格納されているドキュメント -
request.resource
: 書き込みを行った場合に期待される将来のドキュメント(の状態) -
writeFields
: 書き込みを行う場合に、書き込もうとしているフィールドのkeyの一覧
それぞれの違い
resource
ドキュメントによると、
resource 変数は要求されたドキュメントを参照し、resource.data はドキュメントに格納されているすべてのフィールドと値のマップです。
とあるので、現在のドキュメントに格納されているフィールドと値のmapを参照できます。
rulesのそれぞれのオペレーションでは以下の通り。
- read(get, list): 現在のDBに格納されているドキュメント
- create: undefined
- update: 現在のDBに格納されているドキュメント
- delete: 現在のDBに格納されているドキュメント
request.resource
ルールセットが保留中の書き込みを許可する場合は、request.resource 変数にはドキュメントの将来の状態が含められます。ドキュメント フィールドのサブセットのみを変更する update オペレーションの場合、request.resource 変数にはオペレーション後の保留中のドキュメントの状態が含まれます。
つまり、書き込みのオペレーション(crate, update, delete)を実行した後の(保留)ドキュメント状態がmapとして格納される。なので
- read(get, list):
undefined
(writeオペレーション時のみ存在するため) - create: 新規で書き込むドキュメントのフィールドと値のmap
- update: 値の追加更新削除をした後の 将来の状態の フィールドと値のmap。
- delete:
undefined
となる。 update
の場合は、追加更新削除後の 将来の状態 を表すので、あるオペレーションで既存のデータ {A, B}
に {C}
を書き加えて更新する場合、 request.resource.data
には {A, B, C}
が含まれる。
一方で
writeFields
List of fields being written in a write request.
とあり、意訳すると、「書き込みリクエスト時に書き込まれるであろうフィールドのリスト」となる。
- read(get, list): undefined
- create: 書き込むフィールドのkey (
request.resource.data.keys()
と一致) - update: 今回更新追加削除するフィールドのkey (
request.resource.data.keys()
と 必ずしも一致しない 。update時に変更しようとしているフィールドのkeyのみ) - delete: undefined
表にしてみる
実際にそれぞれのオペレーションで、現在のフィールド、書き込むフィールドが与えられた時に、resource
, request.resourcet
, writeFields
の値がどう変化するか表にまとめます。
read(get, list)
現在のフィールド | 書き込むフィールド | resource |
request.resource |
writeFields |
---|---|---|---|---|
{ name: 'mike', age: 25 } |
undefined | { name: 'mike', age: 25 } |
undefined | undefined |
create
現在のフィールド | 書き込むフィールド | resource |
request.resource |
writeFields |
---|---|---|---|---|
undefined | { name: 'mike', age: 25 } |
undefined | { name: 'mike', age: 25 } |
['name', 'age'] |
update
現在のフィールド | 書き込むフィールド | resource |
request.resource |
writeFields |
---|---|---|---|---|
{ name: 'mike', age: 25 } |
{ company: 'Foobar Inc.' } |
{ name: 'mike', age: 25 } |
{ name: 'mike', age: 25, company: 'Foobar Inc.' } |
['company'] |
delete
現在のフィールド | 書き込むフィールド | resource |
request.resource |
writeFields |
---|---|---|---|---|
{ name: 'mike', age: 25 } |
undefined | { name: 'mike', age: 25 } |
undefined | undefined |