我在Firebase商店中使用REST api到PATCH节点。我想阻止更新不存在的节点(因为它们之前被删除)。现在,对不存在的引用执行PATCH会重新创建它。
我研究了设置安全规则,但newData.exists()不区分设置新值和修补,所以我无法弄清楚如何在不限制新创建的情况下允许我想要的内容。
我可以获取引用的快照并在修补之前检查它,但我希望有一种更优雅的方法来实现它而不使用两个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)
鉴于我的应用程序的设计,如果请求条目仍然存在,我只想执行该修补程序。很明显,我可以在修补之前获得快照并执行检查,但这对我来说似乎很尴尬。
答案 0 :(得分:4)
正如我在评论中所说,这些案例之间没有区别:
因此,您必须在应用程序中创建这种区别。
您有几个选择。并非所有这些都适用于REST API,但无论如何我都会提及它们。
Firebase SDK(适用于JavaScript,Java / Android和iOS / OSX)有一个名为transaction
的方法,可让您运行比较和设置操作。
通过该操作,您可以
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
属性。所以您也可以简单地将记录节点作为标记,但删除所有其属性:
requests:
rq123: true
由于Firebase删除了没有值的节点,因此我将true
作为值添加到此处。
使用上述结构,我们只能允许具有id
属性(创建请求时的情况)或已存在id
属性的写入(PATH请求)来自REST API):
".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()"
每种方法都有自己的优点和缺点,因此您必须自己决定哪种方法最适合您的方案。