2016-11-17 119 views
19

表的結構是:火力地堡查詢孩子的孩子包含一個值

  • 聊天
  • - > randomId
  • - > - >參與者
  • - > - - > - > 0: 'NAME1'
  • - > - > - > 1: 'NAME2'
  • - > - > chatItems

我想要做的是查詢聊天表,找到通過傳入的用戶名字符串來保存參與者的所有聊天。

這是我到目前爲止有:

subscribeChats(username: string) { 
    return this.af.database.list('chats', { 
     query: { 
      orderByChild: 'participants', 
      equalTo: username, // How to check if participants contain username 
     } 
    }); 
} 

回答

32

的幾個問題在這裏:

  • 你存儲一個設置作爲固定陣列
  • 你只能索引路徑

Set vs array

一個聊天可以有多個參與者,所以你將它建模爲一個數組。但這實際上並不是理想的數據結構。可能每個參與者只能進行一次聊天。但通過使用陣列,我可以有:

participants: ["puf", "puf"] 

這顯然不是你想到的,但數據結構允許它。你可以嘗試在代碼和安全規則中保證這一點,但如果你從一個更好地隱含地匹配你的模型的數據結構開始,它會更容易。

我的經驗法則:如果你發現自己寫作array.contains(),你應該使用一套

一組是每個孩子最多可以出現一次的結構,所以它自然可以防止重複。

participants: { 
    "puf": true 
} 

這裏的true真的只是虛值:在火力地堡你會成爲一系列的模型,重要的是我們搬到名稱的關鍵。現在,如果我嘗試重新加入該聊天,這將是一個空操作:

participants: { 
    "puf": true 
} 

而當你想加入:

participants: { 
    "john": true, 
    "puf": true 
} 

這是你的要求,最直接的表現:一隻能包含每個參與者一次的集合。

只能索引固定的路徑

通過上述結構,你可以查詢聊天記錄,你是在用:

ref.child("chats").orderByChild("participants/john").equalTo(true) 

的問題是,這需要比您定義的索引關於`參與者/約翰':

{ 
    "rules": { 
    "chats": { 
     "$chatid": { 
     "participants": { 
      ".indexOn": ["john", "puf"] 
     } 
     } 
    } 
    } 
} 

這將工作和表現很好但現在每次有人新加入聊天應用程序,我需要添加另一個索引。這顯然不是一個可擴展的模型。我們需要改變我們的數據結構以允許你想要的查詢。

反轉指標 - 拉類別了,壓扁了的樹大拇指的

第二條規則:模型數據以反映您在您的應用程序顯示的內容。

既然你正在尋找展示的聊天室列表爲用戶,存儲聊天室爲每個用戶:

userChatrooms: { 
    john: { 
    chatRoom1: true, 
    chatRoom2: true 
    }, 
    puf: { 
    chatRoom1: true, 
    chatRoom3: true 
    } 
} 

現在,你可以簡單地確定你與聊天室列表:

ref.child("userChatrooms").child("john") 

然後循環按鍵來獲得每個房間。

你會喜歡有兩個相關的列出你的應用程序:

  • 的聊天室爲特定用戶
  • 參與者在一個特定的聊天室列表中的列表

在這種情況下,你也將在數據庫中同時有兩個列表。

chatroomUsers 
    chatroom1 
    user1: true 
    user2: true 
    chatroom2 
    user1: true 
    user3: true 
userChatrooms 
    user1: 
    chatroom1: true 
    chatroom2: true 
    user2: 
    chatroom1: true 
    user2: 
    chatroom2: true 

由於Firebase建議禁止嵌套數據,我已將兩個列表都拉到了樹的頂層。

擁有這兩個列表在NoSQL解決方案中是完全正常的。在上面的例子中,我們將userChatrooms作爲倒數索引chatroomsUsers

+0

這是一個很棒的解釋。我有我的數據存儲這樣,這使我可以從用戶的列表抓住聊天室,或從聊天室的成員抓住用戶。但它不允許觀察'.childChanged'作爲我所屬的聊天室。如果我嘗試爲'members/myId = true'設置聊天觀察者,那麼我得到未指定的索引錯誤。你會怎麼做呢?我有一個問題發佈在這裏: https://stackoverflow.com/questions/47769044/swift-firebase-using-an-unspecified-index –

+0

@ frank-van-puffelen引用你最後的代碼片段,讓我們說我是「user1 「並且我取得了我所屬的聊天室的所有鑰匙。然後爲每個聊天室密鑰獲取完整的聊天室對象,並在列表中顯示聊天室列表。不過,如果我還需要訪問作爲聊天室一部分的完整用戶對象,那很好。看起來很奇怪,我必須爲每個單個聊天室中的每個單個用戶獲取另一個for循環(2級嵌套for循環!)來獲取該數據。有沒有更好的辦法? – damirstuhec

相關問題