我应该如何构建我的firebase架构以允许搜索功能

时间:2017-09-26 22:57:48

标签: javascript firebase firebase-realtime-database

我的架构如下:

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

问题是这个架构不是搜索友好的,即我想添加一个搜索功能(用户输入单个单词并点击搜索),它返回在其名称或用户名中包含该字符串的用户的所有匹配结果,但是,当前架构不允许这样做,因为只有知道用户ID才能访问名称。

所以我的问题是如何编辑我当前的架构以适应这种搜索功能?

感谢您的任何建议

2 个答案:

答案 0 :(得分:0)

您应该考虑删除名为bio的节点,因为这里不需要它。您更新的数据库结构应如下所示:

enter image description here

现在,您可以使用Firebase查询根据其名称轻松搜索用户,如下所示:

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索引来提高搜索效率。如您所知,将根据用户的名称搜索用户,您可以索引用户节点的名称节点。

要进行必要的索引编制,请转到Firebase控制台,点击数据库,然后选择RULES标签并编辑规则,如下所示:

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

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

答案 1 :(得分:0)

您的数据库结构很好但不幸的是,Firebase查询只能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节点是Firebase根目录的直接子节点,请使用以下代码:

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

您还可以使用与Firebase数据库相同的Denormalization。因此,您可以创建另一个名为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节点,您只能下载此特定节点。这节省了带宽。