安卓:Firebase搜索查询不正常工作

5

我是一个相对新手的Android应用程序开发者。我创建了一个简单的搜索查询,通过名称搜索我的Firebase数据库(请参见下面的代码):

private void firebaseEventSearch(String name) {
    //query to search database based on text in textbox - made case insensitive
    Query eventSearchQuery = eventRef.orderByChild("name").startAt(name.toUpperCase()).endAt(name.toLowerCase() + "\uf8ff");
    eventSearchQuery.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            for (DataSnapshot eventSnapshot : dataSnapshot.getChildren()) {
                Event event = eventSnapshot.getValue(Event.class);
                events.add(event);
            }
            adapter.notifyDataSetChanged();
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {

        }
    });
}

大部分情况下都可以正常工作,但是当我输入字母"A"或"B"时,它会显示所有数据库结果 - 搜索对这两个字母不起作用。此外,如果我输入一个搜索字符串,其中第一个字母与数据库条目匹配,它将显示此数据库条目,即使该字符串的其余部分与其不匹配。

如果有人能帮助我理解为什么这个搜索查询不能正常工作,我将非常感激。


此外,如果我输入一个搜索字符串,其中第一个字母与数据库条目匹配,即使字符串的其余部分不匹配,它也会显示此数据库条目。这种行为似乎完全符合您实现的代码。您正在过滤任何以输入的搜索字符串开头的项目。如果您想要不同的行为,则需要执行不同的查询。例如,您是否在寻找 eventRef.orderByChild("name").equalTo(name) - Frank van Puffelen
嗨,弗兰克,感谢你的回答。我的问题是,如果我的搜索字符串是“cu”,即使这在技术上不匹配搜索字符串,它仍将显示以“co”或“ca”等开头的数据库结果。你知道有没有办法解决这个问题吗? - minikate
如果即使使用我的答案仍然存在问题,请更新您的问题以:1)为“name”使用硬编码值2)包括来自“eventRef”的JSON(作为文本,无截图)。 您可以通过在Firebase数据库控制台上单击溢出菜单(⠇)中的“导出JSON”链接来获取此内容。 - Frank van Puffelen
2个回答

4

Firebase中的查询对大小写非常敏感。尝试使用以下方式。

private void firebaseEventSearch(String name) {
    //query to search database based on text in textbox - made case insensitive
    //Add this part
    String firstLetterCapital = query.substring(0, 1).toUpperCase() + query.substring(1);
    Query eventSearchQuery = eventRef.orderByChild("name").startAt(firstLetterCapital).endAt(firstLetterCapital + "\uf8ff");
    eventSearchQuery.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            for (DataSnapshot eventSnapshot : dataSnapshot.getChildren()) {
                Event event = eventSnapshot.getValue(Event.class);
                events.add(event);
            }
            adapter.notifyDataSetChanged();
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {

        }
    });
}

非常感谢您的帮助!添加后,我的查询将不会返回仅匹配第一个字母的值。然而,我仍然在处理字母"a"和"b"时遇到麻烦...有什么想法吗? - minikate
@minikate,我可以知道events是从哪里来的吗? - Ticherhaz FreePalestine
"events" 是一个数组列表,用于添加各个数据库项。List<Event> events = new ArrayList<>(); - minikate
@minikate 你在使用 Firebase Recycler Adapter 吗? - Ticherhaz FreePalestine
我正在使用RecyclerView,然后使用这个适配器:EventAdapter adapter = new EventAdapter(this, R.layout.eventlist_layout, events); - minikate

3

Firebase数据库查询是区分大小写的。因此,当您调用orderByChild("name")时,所有节点都将按其name属性排序。如果您查看ASCII表,您会发现这将导致小写和大写字符的以下顺序:

A B C .... X Y Z a b c ... x y z

现在,您的查询将获取这些数据的一个片段。如果您正在搜索 A,则该片段为:

A B C .... X Y Z a

所以这比你想要的要多得多。

如果你想在Firebase上允许大小写不敏感的搜索,最常见(但不完全可靠)的实现方式是添加一个额外的属性,以大小写不敏感的方式存储名称。例如:"name_uppercase": "ZUHRAIN"。有了这个,你就可以进行以下搜索:

eventRef.orderByChild("name_uppercase").startAt(name.toUpperCase()).endAt(name.toUpperCase() + "\uf8ff");

另请参见:


先生,是否有可能为大写字母创建一个新的子项?例如:.child(uid).child("upperCase").setValue(modelUserUpperCase); - Ticherhaz FreePalestine
是的,事实上这就是我的回答所提倡的。 name_uppercase 是一个附加属性,它应包含 name 的全部大写值。 - Frank van Puffelen
@FrankvanPuffelen,但是如何显示查询结果呢?我的意思是现在我们可以像平常一样显示,不区分大小写。例如: .child("user").orderByChild("name") ...。那么,如何处理大写的情况呢?因为它们都在子节点“upperCase”中。 - Ticherhaz FreePalestine
抱歉,我很难理解问题所在。您可以通过名称访问“name”或“name_uppercase”属性。如果您难以实现,请使用最小代码重现该问题的新问题。 - Frank van Puffelen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接