我的架构如下:
{
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才能访问名称。
所以我的问题是如何编辑我当前的架构以适应这种搜索功能?
感谢您的任何建议
答案 0 :(得分:0)
您应该考虑删除名为bio的节点,因为这里不需要它。您更新的数据库结构应如下所示:
现在,您可以使用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
节点,您只能下载此特定节点。这节省了带宽。