我有一个有趣的firebase数据库问题。我将带您了解它是如何产生的。
步骤1:用户A发布了一个节点
"20180104" : {
"-L2DNnIkER8XaBOI4n9l" : {
"ImageName" : "EaWpwOXjmFsVatbkBM6V1307.jpg",
"favoriteCount" : 12,
"fileURL" : "https://storage.googleapis.com/...",
"viewCount" : 20,
"reportCount" : 2,
"setID" : "-L2DNknqYN0IzTUN6pe-",
"thumbFileUrl" : "https://storage.googleapis.com/...",
"user" : "uid"
},
"-ABCDnIkER8XaBOI4n9l" : {
"ImageName" : "EaWpwOXjmFsVatbkBM6V1307.jpg",
"favoriteCount" : 3,
"fileURL" : "https://storage.googleapis.com/...",
"viewCount" : 8,
"reportCount" : 2,
"setID" : "-L2DNknqYN0IzTUN6pe-",
"thumbFileUrl" : "https://storage.googleapis.com/...",
"user" : "uid"
},
第2步:用户B从firebase中提取此信息。现在,他们在应用程序中本地拥有JSON。
步骤3:用户A从firebase中的节点删除第二个图像密钥。
Step4:firebase中生成的JSON为:
"20180104" : {
"-L2DNnIkER8XaBOI4n9l" : {
"ImageName" : "EaWpwOXjmFsVatbkBM6V1307.jpg",
"favoriteCount" : 12,
"fileURL" : "https://storage.googleapis.com/...",
"viewCount" : 20,
"reportCount" : 2,
"setID" : "-L2DNknqYN0IzTUN6pe-",
"thumbFileUrl" : "https://storage.googleapis.com/...",
"user" : "uid"
},
// second node is now deleted
步骤5:现在用户A决定“喜欢”第二张照片,导致写入数据库。
第6步:我们在firebase中生成的数据库:
"20180104" : {
"-L2DNnIkER8XaBOI4n9l" : {
"ImageName" : "EaWpwOXjmFsVatbkBM6V1307.jpg",
"favoriteCount" : 12,
"fileURL" : "https://storage.googleapis.com/...",
"viewCount" : 20,
"reportCount" : 2,
"setID" : "-L2DNknqYN0IzTUN6pe-",
"thumbFileUrl" : "https://storage.googleapis.com/...",
"user" : "uid"
},
"-ABCDnIkER8XaBOI4n9l" : {
"favoritecount": 13
// now we have corrupted data :(
}
我想阻止步骤6中的最终写入。安全规则方面但似乎无法弄清楚它们是如何工作的。说“..如果父键不存在,不写信给它?”
答案 0 :(得分:1)
假设您的pic密钥没有像您的示例中那样重复,您可以阻止对不存在的节点进行写入:
"picDirectory" {
"$picID": {
".write": "data.exists()"
}
}
以下是相关的docs。
答案 1 :(得分:0)
您的通用ID实际上是重复的,即-L2DNnIkER8XaBOI4n9l
是完全相同的密钥。图像也是完全相同的图像。看起来每个图像都有一个唯一的密钥。修复后,使用事务来处理共享计数器,例如喜欢或启动。
例如,在示例社交博客应用中,您可以允许 用户可以发布明星和非明星帖子并跟踪帖子中有多少个明星 收到如下:
function toggleStar(postRef, uid) { postRef.transaction(function(post) { if (post) { if (post.stars && post.stars[uid]) { post.starCount--; post.stars[uid] = null; } else { post.starCount++; if (!post.stars) { post.stars = {}; } post.stars[uid] = true; } } return post; }); }
使用交易可以防止星号不正确 多个用户同时或客户端同一个帖子 陈旧的数据。如果事务被拒绝,服务器将返回 客户端的当前值,再次使用 更新的价值。这将重复,直到交易被接受或您 中止交易。