2017-07-21 43 views
1

在我的應用程序中,用戶可以分組上傳圖片。可以將Fanout方法替換爲Firebase中的ref.orderByChild(key).equalTo(value)嗎?

有兩頁顯示這些圖片。

我有兩個要求。

  1. 顯示用戶上傳的圖像列表。
  2. 顯示上傳到組的圖像列表。

從我的火力教程中學,我瞭解到的數據扇出是一個良好的冗餘機制是會加快的寫入速度的成本,因爲有更多的搜索請求比寫請求這是很好的查找時間。所以我創建了以下結構。

扇出方法

{ 
    "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" 
     }] 
    }, 
} 

代碼來檢索

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 

但是這引起了顯著頭痛,因爲如果要更新後,你有參考從組後 - 發帖查詢,你必須更新用戶發佈側,反之亦然。

這需要我和groupKey添加USERKEY到後期數據結構,因此雲功能迅速找到對方對方。此外,我可能需要像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); 
     } 
    }); 

寫完所有這些之後,我開始感到筋疲力盡。 我又試了一次。 相反,我只是使用.orderBy(key).equalTo(value)來檢索非扇出數據?

無扇出方法

{ 
    "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 = ...; 
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對象都由它的所有子鍵排序,這樣開發人員就不必管理扇出了?

回答

1

假設您希望用戶擁有對自己擁有的帖子的讀取權限。

我們有

"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" 
     } 
    ] 

user_key_1想要訪問後。 但我們不希望她看到user_key_2。 如果我們要使用排序依據,我們將不得不調用

... 
.child("post").orderBy("userKey").equalTo("user_key_2"); 

但由於我們不能值的範圍內給予選擇性的驗證規則(在這種情況下,後陣列),我們會最終不得不請執行下列操作。

"post":{ 
    .read:true, 
    .write:true 
} 

惡意的黑客可以訪問其他東西,所以我們最終會得到一個可以暴露的數據庫。 因此,要使用驗證規則的方式,避免orderBy和使用數據複製。

暗示任何人認爲它應該在服務器端, 這是我做了一個。

exports.multiUpdate = functions.database.ref( '/後/ {postKey}')onWrite(事件=> { 變種交= event.data.val();

變種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 /」上,並且它也會更新相應的位置。

相關問題