背景:
假设Firestore上有产品和订单集合。
订单有很多产品,即(伪架构):
products {
name: string
}
orders {
items: [{
product_id: (ref products)
quantity: number
}]
}
使用这些安全规则:
match /products/{document=**} {
allow read, write: if request.auth != null;
}
match /orders/{document=**} {
allow read, write: if request.auth != null;
}
情景:
现在,假设我们已经创建了产品A.
然后,我们为产品A创建了订单1.
接下来,假设我们从产品系列中删除了产品A(已在订单1中使用)。
这将使订单1仍然引用已删除的产品A.
问题:
有没有办法编写安全规则来阻止删除订单上使用的产品?
答案 0 :(得分:0)
首先,如果目标只是一致性,您可以使用函数删除对A的引用,这样就没有断开的链接。
但是,如果你特意想要在链接时阻止删除,那么你需要一个不同的策略,因为目前无法在安全规则中查询另一条路径。
非规范化:保留产品中的参考列表
您的数据中包含以下内容:
"{product_id}": {
"name": "...",
"orders": {
"order_id": true
}
}
允许你写这样的规则:
function isAuthenticated() {
return auth != null;
}
function hasLinks(resource) {
return !resource.data.links;
}
match /products/{pid} {
allow delete: if isAuthenticated() && !hasLinks(request.resource);
}
其他想法
使用功能:我的第一直觉是队列方法(您将删除排队到服务器,服务器决定是否有产品链接,删除它或拒绝请求)。但这不适用于您当前的结构,因为您无法跨子集查询以在每个订单子集合中查找对产品的引用。您仍然需要一个非规范化的产品订单列表来使用此产品(这与我上面的解决方案非常相似)。
归档项目而不是删除项目:可能并不强烈需要实际删除项目,因此归档它们可以避免整个问题集。