如何防止更新不存在的节点?
How do I prevent updates to nonexistent nodes?
我正在使用 REST api 来修补我的 Firebase 商店中的节点。我想阻止更新不存在的节点(因为它们之前已被删除)。现在,对不存在的引用执行 PATCH 操作会重新创建它。
我研究了设置安全规则,但是 newData.exists() 不区分设置新值和修补,所以我不知道如何在不限制新创建的情况下允许我想要的内容。
我可以获得引用的快照并在 PATCHING 之前进行检查,但我希望有一种更优雅的方式来完成它而无需使用两个 REST 调用。
编辑:一些代码!
我的 Firebase 架构如下所示:
requests:
rq123:
id: '123'
sender: '1'
recipient: '2'
expiration: '1234567',
filled: false,
filledDate: '',
新请求是从移动客户端写入的。我的服务器可以使用 REST api 更新这些请求条目。使用 python-firebase 库,看起来像:
request_ref = firebase_root + '/requests/' + request.id
patch_data = {
'filled':'true',
'filled_date':'7654321'
}
firebase_conn.patch(request_ref, patch_data)
考虑到我的应用程序的设计,我只想在请求条目仍然存在时执行该修补程序。很明显,我可以在修补之前获取快照并以这种方式执行检查,但这对我来说似乎很尴尬。
正如我在评论中所说,这些情况之间没有区别:
- 正在写入不存在的数据库位置还
- 正在写入不存在的数据库位置不再
所以您必须在您的申请中做出区分。
您有几个选择。并非所有这些都适用于 REST API,但为了完整起见,我还是会提及它们。
交易更新
Firebase SDK(适用于 JavaScript、Java/Android 和 iOS/OSX)有一个名为 transaction
的方法,它允许您 运行 比较- and-set操作。
通过该操作,您可以
ref.transaction(function(current) {
if (current) {
current.filled: true,
current.filled_date:'7654321'
}
return current;
});
但由于此方法在 REST API 上不可用,因此不适用于您的场景。
标记删除的记录
或者您可以标记已删除的记录,而不是实际删除它们:
requests:
rq123:
id: '123'
sender: '1'
recipient: '2'
expiration: '1234567'
filled: false
filledDate: ''
DELETED: true
您还可以在伪删除请求时删除所有其他属性,即
requests:
rq123:
DELETED: true
那么在你的安全规则中,当这个标志存在时你可以拒绝写操作:
".write": "data.child('DELETED').val() != true"
标记记录的方法有很多种。例如,在您的情况下,记录节点似乎总是有一个 id
属性。所以你也可以简单地将记录节点保留为标记,但删除 all 它的属性:
requests:
rq123: true
由于 Firebase 删除了没有值的节点,我将 true
放在这里作为值。
使用上述结构,我们只能允许具有 id
属性(创建请求时的情况)或 id
属性 已经存在(来自 REST API 的 PATH 请求):
".write": "newData.child('id').exists() || data.child('id').exists()"
保留已删除节点的列表
我的最终方法是保留已删除请求键的列表:
requests:
rq123:
id: '123'
sender: '1'
recipient: '2'
expiration: '1234567'
filled: false
filledDate: ''
deleted:
rq456: true
rq789: true
我们再次为已删除的节点设置一个虚拟值 true
,以防止 Firebase 删除它们。
使用此结构,当您要写入的密钥存在于 deleted
请求列表中时,您可以拒绝写入操作:
".write": "!root.child('deleted').child(newData.key()).exists()"
每种方法都有其优点和缺点,因此您必须自己决定哪种方法最适合您的情况。
我正在使用 REST api 来修补我的 Firebase 商店中的节点。我想阻止更新不存在的节点(因为它们之前已被删除)。现在,对不存在的引用执行 PATCH 操作会重新创建它。
我研究了设置安全规则,但是 newData.exists() 不区分设置新值和修补,所以我不知道如何在不限制新创建的情况下允许我想要的内容。
我可以获得引用的快照并在 PATCHING 之前进行检查,但我希望有一种更优雅的方式来完成它而无需使用两个 REST 调用。
编辑:一些代码!
我的 Firebase 架构如下所示:
requests:
rq123:
id: '123'
sender: '1'
recipient: '2'
expiration: '1234567',
filled: false,
filledDate: '',
新请求是从移动客户端写入的。我的服务器可以使用 REST api 更新这些请求条目。使用 python-firebase 库,看起来像:
request_ref = firebase_root + '/requests/' + request.id
patch_data = {
'filled':'true',
'filled_date':'7654321'
}
firebase_conn.patch(request_ref, patch_data)
考虑到我的应用程序的设计,我只想在请求条目仍然存在时执行该修补程序。很明显,我可以在修补之前获取快照并以这种方式执行检查,但这对我来说似乎很尴尬。
正如我在评论中所说,这些情况之间没有区别:
- 正在写入不存在的数据库位置还
- 正在写入不存在的数据库位置不再
所以您必须在您的申请中做出区分。
您有几个选择。并非所有这些都适用于 REST API,但为了完整起见,我还是会提及它们。
交易更新
Firebase SDK(适用于 JavaScript、Java/Android 和 iOS/OSX)有一个名为 transaction
的方法,它允许您 运行 比较- and-set操作。
通过该操作,您可以
ref.transaction(function(current) {
if (current) {
current.filled: true,
current.filled_date:'7654321'
}
return current;
});
但由于此方法在 REST API 上不可用,因此不适用于您的场景。
标记删除的记录
或者您可以标记已删除的记录,而不是实际删除它们:
requests:
rq123:
id: '123'
sender: '1'
recipient: '2'
expiration: '1234567'
filled: false
filledDate: ''
DELETED: true
您还可以在伪删除请求时删除所有其他属性,即
requests:
rq123:
DELETED: true
那么在你的安全规则中,当这个标志存在时你可以拒绝写操作:
".write": "data.child('DELETED').val() != true"
标记记录的方法有很多种。例如,在您的情况下,记录节点似乎总是有一个 id
属性。所以你也可以简单地将记录节点保留为标记,但删除 all 它的属性:
requests:
rq123: true
由于 Firebase 删除了没有值的节点,我将 true
放在这里作为值。
使用上述结构,我们只能允许具有 id
属性(创建请求时的情况)或 id
属性 已经存在(来自 REST API 的 PATH 请求):
".write": "newData.child('id').exists() || data.child('id').exists()"
保留已删除节点的列表
我的最终方法是保留已删除请求键的列表:
requests:
rq123:
id: '123'
sender: '1'
recipient: '2'
expiration: '1234567'
filled: false
filledDate: ''
deleted:
rq456: true
rq789: true
我们再次为已删除的节点设置一个虚拟值 true
,以防止 Firebase 删除它们。
使用此结构,当您要写入的密钥存在于 deleted
请求列表中时,您可以拒绝写入操作:
".write": "!root.child('deleted').child(newData.key()).exists()"
每种方法都有其优点和缺点,因此您必须自己决定哪种方法最适合您的情况。