5

I am fairly new to Android app development. I have created a simple search query that searches my firebase database by name (see code below):

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) {

        }
    });
}

It works fine for the most part, however, it will display all database results when I type in the letters "A" or "B" - the search does not work for these two letters. Also, if I type in a search string where the first letter matches a database entry, it will display this database item, even if the rest of the string does not match it.

I would really appreciate if anyone could help me understand why this search query is not working properly.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
minikate
  • 305
  • 1
  • 6
  • 16
  • "Also, if I type in a search string where the first letter matches a database entry, it will display this database item, even if the rest of the string does not match it." That behavior seems to be exactly in line with the code you implemented. You're filtering for any items that start with the search string that was entered. If you want a different behavior, you'll need to perform a different query. For example, aren't you looking for `eventRef.orderByChild("name").equalTo(name)`. – Frank van Puffelen Jan 12 '19 at 01:26
  • Hi Frank, thank for your answer. My problem with this is that if my search string is "cu", it will still show database results that start with "co" or "ca", etc, even though this technically doesn't match the search string. Do you know if there is a way around this? – minikate Jan 12 '19 at 12:14
  • If even with my answer you're still having problems, update your question to: 1) use a hard-coded value for `name` 2) include the JSON from `eventRef` (as text, no screenshots). You can get this by clicking the "Export JSON" link in the overflow menu (⠇) on your [Firebase Database console](https://console.firebase.google.com/project/_/database/data). – Frank van Puffelen Jan 12 '19 at 14:50

2 Answers2

4

Query in Firebase is really sensitive with the capital letter. Try this one.

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) {

        }
    });
}
Ticherhaz FreePalestine
  • 2,738
  • 4
  • 20
  • 46
3

Firebase Database queries are case-sensitive. So when you call orderByChild("name") all nodes are ordered by their name property. If you look at an ASCII chart, you'll see that this will lead to this order for lowercase and uppercase characters:

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

Now your query takes a slice of this data. If you're searching for A, the slice is:

A B C .... X Y Z a

So that's way more than you want.

If you want to allow case-indifferent search on Firebase, the most common (but not completely failsafe) way to implement it is to add an extra property that stores the name in an case-indifferent way. E.g. "name_uppercase": "ZUHRAIN". With that you can search on:

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

Also see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Sir, is that possible to make a new child for uppercase? Example: `.child(uid).child("upperCase").setValue(modelUserUpperCase);` – Ticherhaz FreePalestine Jan 12 '19 at 23:46
  • Yes, that is in fact what my answer promotes. `name_uppercase` is an additional property that should contain the all-uppercase value of `name`. – Frank van Puffelen Jan 12 '19 at 23:58
  • @FrankvanPuffelen but how to display back the query? I mean right now we can display like normal, without the uppercase. ex: `.child("user").orderByChild("name") ...` . Then, how to do for the uppercase, because all of them in child 'upperCase'. – Ticherhaz FreePalestine Jan 13 '19 at 00:50
  • Sorry, I'm having a hard time understanding what the problem is. You can access either the `name` or `name_uppercase` properties by their name. If you're having a hard time implementing that, open a new question with the [minimal code that reproduces that problem](http://stackoverflow.com/help/mcve). – Frank van Puffelen Jan 13 '19 at 01:13