我有一个用例,我需要用户向Firebase中的某个位置提供一组数据,但不能同时更改该位置的各个子节点。
作为一个例子,假设我有一个用户能够写入一个不同的系统正在观看的树requests
,以便它可以处理请求。此外,我们不是使用.push()
生成Firebase pushID来唯一标识请求,而是只有一个写入请求的单一位置。结构可能如下所示:
requests: {
UserID1: {
requestParam1: "Some parameter",
requestParam2: "Another parameter"
}
}
要明确的是,处理请求的系统将监听requests/UserID1
,以便通知结构的任何更改并处理请求。
我们还要说requestParam1
和requestParam2
都是必需的。每次写入UserID1
节点时都需要这些参数的原因是为了防止用户仅写入requestParam1
,然后处理请求的系统无法获得基本上接收新 requestParam1
和旧 requestParam2
的请求。
很容易确保在写入UserID1
时,包含两个参数,但我无法弄清楚如何直接停止对子节点的写入。
到目前为止,这是我的规则:
"requests": {
"$userID": {
".write": "auth !== null && newData.exists()",
".validate": "newData.hasChildren(['requestParam1', 'requestParam2'])"
"requestParam1": {
".validate": "newData.isString()"
},
"requestParam2": {
".validate": "newData.isString()"
}
"$other": {
".validate": false
}
}
}
如果我尝试在没有其中一个请求参数的情况下写入UserID1
,它会拒绝写入 - 这是正确的。但是,当我直接写入UserID1/requestParam1
时,尝试成功,这不是理想的行为。
我在两个".write": false
中都包含requestParam
个规则,但仍然允许写入。我相信这是因为写入被父节点中的写规则认为是允许的,因此级联到子节点。根据文档,我认为没有办法解决这个问题。但是,我认为我会变得聪明,并让每个子节点检查newData.parent()
的子内容,如下所示:
"requests": {
"$userID": {
".write": "auth !== null && newData.exists()",
".validate": "newData.hasChildren(['requestParam1', 'requestParam2'])"
"requestParam1": {
".validate": "
newData.parent().exists() &&
newData.parent().hasChildren(['requestParam1', 'requestParam2']) &&
newData.isString()
"
},
"requestParam2": {
".validate": "
newData.parent().exists() &&
newData.parent().hasChildren(['requestParam1', 'requestParam2']) &&
newData.isString()
"
}
"$other": {
".validate": false
}
}
}
我不确定是否添加newData.parent().exists()
支票,所以我把它放在那里以获得良好的衡量标准,但我认为newData().parent().hasChildren([...])
规则会使这一切都有效,但我错了。仍然允许写给个别孩子。
想法?
编辑1:
我还尝试将先前位于newData.hasChildren([...])
部分的.validate
规则移至.write
规则中的$userID
部分,但没有运气。
答案 0 :(得分:0)
正如@AnidMonsur所指出的那样,newData
“是现有数据的'合并'加上正在编写的新数据”(from the docs),所以它实际上不是只是< / em>新数据,这肯定使问题更难回答。
实现此目标的一种可能方法是确保将写入每个位置的newData与已在该位置的数据(如果存在)不同。但是,如果用户打算将相同的数据写入现场,则这不是一个可行的解决方案。
但是,我认为我有一个可行的替代方案。对于每个数据,即requestParam1
和requestParam2
,规则应强制规则的优先级等同于now并确保优先级数据匹配。这将强制客户端发出请求以在每个数据的请求中包括优先级。这导致以下规则:
"requests": {
"$userID": {
".write": "auth !== null && newData.exists()",
".validate": "newData.hasChildren(['requestParam1', 'requestParam2'])"
"requestParam1": {
".validate": "
newData.isString() &&
newData.getPriority() !== null &&
newData.getPriority() === now &&
newData.parent().child('requestParam2').getPriority() === newData.getPriority()
"
},
"requestParam2": {
".validate": "
newData.isString() &&
newData.getPriority() !== null &&
newData.getPriority() === now &&
newData.parent().child('requestParam1').getPriority() === newData.getPriority()
"
}
"$other": {
".validate": false
}
}
}
我不确定是否有办法颠覆这个策略...我想两个用户在同一时间写两个位置是可能,但我'我不确定如何避免这种情况(另外,似乎不太可能)。
另外,作为附注,如果有人想知道如何在数据中包含优先级(如果它只是字符串/数字/布尔类型),则可以按如下方式构建写入数据:
//before:
var data = "Some data"
/after:
var data = {
".value": "Some data",
".priority": Firebase.ServerValue.TIMESTAMP
}