2017-09-26 26 views
0

我的架構如下:我應該如何構建我的火力模式以允許搜索功能

{ 
    users: { 
     user_id_of_who_this_username_belongs_to: { 
     bio: { 
      name: name1, 
      username: test1 
     } 
     }, 
     user_id_of_who_this_username_belongs_to: { 
     bio: { 
      name: name2, 
      username: test2 
     } 
     }, 

    }, 
    usernames: { 
     test1: user_id_of_who_this_username_belongs_to, 
     test2: user_id_of_who_this_username_belongs_to, 
    } 
} 

問題是這樣的架構不是搜索友好的,即我要添加一個搜索功能(用戶輸入單個單詞和單擊搜索),它返回在其名稱或用戶名中包含該字符串的用戶的所有匹配結果,但是,當前模式不允許使用該名稱,因爲只有知道用戶標識時才能訪問名稱。

所以我的問題是如何編輯我當前的模式以適應此搜索功能?

感謝您的任何建議

回答

0

你應該考慮刪除指定的生物節點,因爲它是沒有必要在這裏。您更新的數據庫結構應該像下面給出的一個:

enter image description here

現在,你可以搜索基於通過使用火力地堡查詢自己名字的用戶,如下圖所示輕鬆:

DatabaseReference databaseReference= FirebaseDatabase.getInstance().getReference(); 
Query query=databaseReference.child("users").orderByChild("name").equalTo("entered user name"); 
query.addListenerForSingleValueEvent(new ValueEventListener() { 
    @Override 
    public void onDataChange(DataSnapshot dataSnapshot) { 

     for(DataSnapshot snapshot:dataSnapshot.getChildren()){ 
      User user =snapshot.getValue(User.class); 

     } 
    } 

    @Override 
    public void onCancelled(DatabaseError databaseError) { 

    } 
}); 

這將工作完美適用於小型數據庫,但對於非常大型的數據庫,您可以使用Firebase索引來提高搜索效率。由於您已經知道用戶將根據他/她的名字進行搜索,因此您可以索引用戶節點的名稱節點。

爲了完成所需的索引,去你的火力地堡控制檯中,單擊數據庫,然後選擇規則選項卡和編輯您的規則,如下圖所示:

{ 
    "rules": { 
    ".read": "auth != null", 
    ".write": "auth != null", 

    "users": { 
    ".indexOn": ["name"]  
    } 
    } 
+0

謝謝,我會在今天晚些時候嘗試一下,當我有時間回到你身邊時,就我的生物財產而言,因爲我有另一個屬性,我忽略了作爲用戶的子女,即: {user_id:{bio:{...},otherProperty:{...}}。順便說一下,您可以使用JavaScript SDK編寫這些代碼?謝謝 – linasmnew

+0

對不起,但我不熟悉JS :( –

0

你的數據庫結構是好的,但不幸的是,火力地堡查詢只能order/filter by a single property。因此,Firebase中沒有WHERE子句。你應該怎麼做,是將一個名爲name_username的複合值耦合起來。你的數據庫結構應該是這樣的:

{ 
    users: { 
     user_id_of_who_this_username_belongs_to: { 
     name: "name1", 
     username: "test1", 
     name_username: "name1_test1" 
     }, 
     user_id_of_who_this_username_belongs_to: { 
     name: "name2", 
     username: "test2", 
     name_username: "name2_test2" 
     }, 

    } 
} 

正如你可能會看到,我已增加了對每個用戶的新複合值name_username。這意味着您可以根據此新的name_username字段查詢您的Firebase數據庫。請注意,我刪除了bio節點,因爲您的結構中不需要額外的孩子。假設users節點是你的火力地堡根的直接子,請使用如下代碼:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference(); 
DatabaseReference usersRef = rootRef.child("users"); 
ValueEventListener eventListener = new ValueEventListener() { 
    @Override 
    public void onDataChange(DataSnapshot dataSnapshot) { 
     String searchedNameOrUserName = "test2"; 
     for(DataSnapshot ds : dataSnapshot.getChildren()) { 
      String name_username = ds.child("name_username").getValue(String.class); 
      if(name_username.contains(searchedNameOrUserName)) { 
       Log.d("TAG", name_username); 
      } 
     } 
    } 

    @Override 
    public void onCancelled(DatabaseError databaseError) {} 
}; 
usersRef.addListenerForSingleValueEvent(eventListener); 

我給你舉個例子搜索test2關鍵字。 searchNameOfUserName文本將是用戶輸入的確切搜索名稱或用戶名。

爲了更好地理解,我建議你看到這個tutorial

您也可以使用Denormalization,這是Firebase數據庫的正常使用方式。因此,您可以創建另一個名爲namesUserNames的節點,您可以在搜索後僅添加所需的信息。你的新的節點應該是這樣的:

{ 
    namesUserNames: { 
     user_id_of_who_this_username_belongs_to: { 
      name_username: "name1_test1" 
     }, 
     user_id_of_who_this_username_belongs_to: { 
      name_username: "name2_test2" 
     }, 
    } 
} 

使用這個例子中,你不需要下載整個users節點,你就可以只下載這個特殊的一個。這節省了帶寬。

+0

謝謝,今天晚些時候我會試試看,當我有時間回到你身上,就我的生物特性而言,因爲我有另一個屬性我忽略了作爲用戶的孩子,即:{user_id:{bio:{...},otherProperty:{...}}順便說一句,您可以使用JavaScript SDK編寫該代碼?謝謝 – linasmnew

+0

好的,如果你需要那個'生物'的孩子,只需在'.child(「users」)之後添加它'是的,我不知道javascript,但是流程如上面和那個教程中所解釋的那樣。 –

+0

添加Javascript –

相關問題