在Firebase中,扇出方法是否可以替换为ref.orderByChild(key).equalTo(value)?
在我的应用程序中,用户可以分组上传图片 有两个页面显示这些图片 我有两个要求在Firebase中,扇出方法是否可以替换为ref.orderByChild(key).equalTo(value)?,firebase,database,nosql,Firebase,Database,Nosql,在我的应用程序中,用户可以分组上传图片 有两个页面显示这些图片 我有两个要求 显示用户上载的图像列表 显示上载到组中的图像列表 从firebase教程中我了解到,数据扇出是一种很好的冗余机制,它将以写入速度为代价加快查找时间,写入速度很好,因为查找请求比写入请求多。所以我创建了以下结构 扇出法 { "user": [ {key: "user_key_1"}, {key: "user_key_2"}, {key: "user_key_3"},
{
"user": [
{key: "user_key_1"},
{key: "user_key_2"},
{key: "user_key_3"},
],
"group": [
{key: "group_key_1"},
{key: "group_key_2"}
],
"post": [
{
key: "post_key_1"
},
{
key: "post_key_2"
},
{
key: "post_key_3"
},
],
"user-post": {
user_key_1:[{
key: "post_key_1"
}],
user_key_2:[{
key: "post_key_2"
},{
key: "post_key_3"
}]
},
"group-post": {
group_key_1:[{
key: "post_key_2"
}],
group_key_2:[{
key: "post_key_1"
},{
key: "post_key_3"
}]
},
}
{
"user": [
{key: "user_key_1"},
{key: "user_key_2"},
{key: "user_key_3"},
],
"group": [
{key: "group_key_1"},
{key: "group_key_2"},
],
"post": [
{
key: "post_key_1"
groupKey: "group_key_2"
userKey: "user_key_1"
},
{
key: "post_key_2"
groupKey: "group_key_1"
userKey: "user_key_2"
},
{
key: "post_key_3"
groupKey: "group_key_2"
userKey: "user_key_2"
}
]
}
检索代码
String userKey = ...;
database.child("user-post").child(userKey).addValueEventListener(...)
// returns list of posts owned by userKey
String groupKey = ...;
database.child("group-post").child(groupKey).addValueEventListener(...)
// returns list of posts posted on groupKey
String userKey = ...;
databaseReference.child("post").orderByChild("userKey").equalTo(userKey).addValueEventListener(...)
// returns list of posts owned by userKey
String groupKey = ...;
databaseReference.child("post").orderByChild("groupKey").equalTo(groupKey).addValueEventListener(...)
// returns list of posts posted on groupKey
但是这引起了极大的头痛,因为如果您想更新帖子,并且您有来自组帖子查询的帖子引用,那么您必须更新用户帖子端,反之亦然
这需要我将userKey和groupKey添加到post数据结构中,以便云函数能够快速找到另一端。此外,我可能需要类似lastUpdatedTimestamp的东西来查看谁过时了
exports.userPostToBusinessPost = functions.database.ref('/user-post/{userKey}')
.onWrite(event => {
const userPostRef = event.data.val();
const businessPostRef = event.data.adminRef.root.child('business-post').child(post.businessKey);
if(userPostRef.lastUpdatedTimestamp <= businessPostRef.lastUpdatedTimestamp){
return;
}else{
return businessPost.set(event.data);
}
});
exports.businessPostToUserPost = functions.database.ref('/business-post/{businessKey}')
.onWrite(event => {
const businessPostRef = event.data.val();
const userPostRef = event.data.adminRef.root.child('user-post').child(post.userKey);
if(userPostRef.lastUpdatedTimestamp <= businessPostRef.lastUpdatedTimestamp){
return;
}else{
return userPostRef.set(event.data);
}
});
检索代码
String userKey = ...;
database.child("user-post").child(userKey).addValueEventListener(...)
// returns list of posts owned by userKey
String groupKey = ...;
database.child("group-post").child(groupKey).addValueEventListener(...)
// returns list of posts posted on groupKey
String userKey = ...;
databaseReference.child("post").orderByChild("userKey").equalTo(userKey).addValueEventListener(...)
// returns list of posts owned by userKey
String groupKey = ...;
databaseReference.child("post").orderByChild("groupKey").equalTo(groupKey).addValueEventListener(...)
// returns list of posts posted on groupKey
我还应该使用扇出方法吗?是不是因为“orderByChild”的成本很高?如果是这样,为什么Firebase会有一种隐式扇出机制,在这种机制中,只要我们保存一些数据,任何json对象都会按其所有子键进行排序,这样开发人员就不必自己管理扇出?假设您希望用户拥有对自己拥有的帖子的读取权限 我们有
"post": [
{
key: "post_key_1"
groupKey: "group_key_2"
userKey: "user_key_1"
},
{
key: "post_key_2"
groupKey: "group_key_1"
userKey: "user_key_2"
},
{
key: "post_key_3"
groupKey: "group_key_2"
userKey: "user_key_2"
}
]
用户\密钥\ 1想要访问post。
但我们不想让她看到用户2。
如果我们想使用orderBy,我们必须打电话
...
.child("post").orderBy("userKey").equalTo("user_key_2");
但是,由于我们不能在值(在本例中为post数组)中给出选择性验证规则,因此我们最终不得不执行以下操作
"post":{
.read:true,
.write:true
}
恶意黑客可以访问其他东西,因此我们最终将得到一个可以公开的数据库。
因此,要按预期方式使用验证规则,请避免orderBy,并使用数据复制
对认为应该在服务器端执行的任何人的提示,
我是这样做的
exports.multiUpdate=functions.database.ref('/post/{postKey}').onWrite(事件=>{
var post=event.data.val()
var fanoutObject={}
fanoutObject['/user-post/'+ post.authorUid+"/"+post.key] = post;
fanoutObject['/group-post/'+post.groupKey+"/"+post.key] = post;
return event.data.adminRef.root.update(fanoutObject);
}))
这种方式很好,因为您只需始终保存到客户端的“/post/”上,这也会更新相应的位置