Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to search list of data from firebase firestore using android searchView

I'm using the Cloud Firestore of Firebase to store users and the android Searchview to provide search fonctionnality. When a user search for "jonathan" for example, if he begin typing "j" i want to bring in all users with the name starting par "j". How can i achieve this ?

Here is what i have tried:

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);

        MenuItem search = menu.findItem(R.id.action_search);
        SearchView searchView = (SearchView) search.getActionView();

        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {

            @Override
            public boolean onQueryTextSubmit(String query) {
                //Toast.makeText(MainActivity.this, "SEARCH " + query, Toast.LENGTH_LONG).show();
                searchUsers(query);
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                //Toast.makeText(MainActivity.this, "SEARCH " + newText, Toast.LENGTH_LONG).show();
                searchUsers(newText);
                return false;
            }
        });

        return true;
    }

Getting the user from Firebase:

private void searchUsers(String recherche) {
    if(recherche.length() > 0)
    recherche = recherche.substring(0,1).toUpperCase() + recherche.substring(1).toLowerCase();
    listUsers = new ArrayList<>();

    db.collection("users").whereGreaterThanOrEqualTo("name", recherche)
            .addSnapshotListener(new EventListener<QuerySnapshot>() {
                @Override
                public void onEvent(@Nullable QuerySnapshot snapshots,
                                    @Nullable FirebaseFirestoreException e) {
                    if (e != null) {
                        System.err.println("Listen failed:" + e);
                        return;
                    }
                    listUsers = new ArrayList<User>();

                    for (DocumentSnapshot doc : snapshots) {
                        User user = doc.toObject(User.class);
                        listUsers.add(user);
                    }
                    updateListUsers(listUsers);
                }
            });
}

This works only for the first letter "j" as soon as i add "ja" for example i still have all the "jonathan" displayed

like image 950
Moussa Diallo Avatar asked Dec 31 '18 21:12

Moussa Diallo


People also ask

How do I access firestore database on Android?

Inside that click on Firebase. After clicking on Firebase, you can get to see the right column mentioned below in the screenshot. Inside that column Navigate to Firebase Cloud Firestore. Click on that option and you will get to see two options on Connect app to Firebase and Add Cloud Firestore to your app.

How do I get a collection list on firestore?

js admin clients have listCollections() on Firestore to get that list. Or, if you're looking for subcollections nested under a document, use DocumentReference. listCollections(). If you want to get a list on any platform, you should maintain that list yourself in a known collection inside a known document id.

How do I get data from a firestore document?

To read a single document, we can use DocumentReference's get() method that returns a Task<DocumentSnapshot>, while reading multiple documents from a collection or Query, we can use Firestore Query's get() method that returns an object of type Task<QuerySnapshot>. Both methods read the data only once.


2 Answers

Thanks to the suggestion of @Oby if found the solution. In fact i dont really need to query the database every time the search is triggered since i have the list of users. I just have to make the search on the list like this: We get the list first:

private void getUsers() {
        db.collection("users").whereEqualTo("etat", 1)
                .addSnapshotListener(new EventListener<QuerySnapshot>() {
                    @Override
                    public void onEvent(@Nullable QuerySnapshot snapshots,
                                        @Nullable FirebaseFirestoreException e) {
                        if (e != null) {
                            System.err.println("Listen failed:" + e);
                            return;
                        }
                        listUsers = new ArrayList<User>();

                        for (DocumentSnapshot doc : snapshots) {
                            User user = doc.toObject(User.class);
                            listUsers.add(user);
                        }
                        updateListUsers(listUsers);
                    }
                });
    }

Here is the search function:

private void searchUsers(String recherche) {
        if (recherche.length() > 0)
            recherche = recherche.substring(0, 1).toUpperCase() + recherche.substring(1).toLowerCase();

        ArrayList<User> results = new ArrayList<>();
        for(User user : listUsers){
            if(user.getName() != null && user.getName().contains(recherche)){
                results.add(user);
            }
        }
        updateListUsers(results);
    }

Here i notify the the Adapter of the RecyclerView that the data changed:

private void updateListUsers(ArrayList<User> listUsers) {

        // Sort the list by date
        Collections.sort(listUsers, new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                int res = -1;
                if (o1.getDate() > (o2.getDate())) {
                    res = 1;
                }
                return res;
            }
        });

        userRecyclerAdapter = new UserRecyclerAdapter(listUsers, InvitationActivity.this, this);
        rvUsers.setNestedScrollingEnabled(false);
        rvUsers.setAdapter(userRecyclerAdapter);
        layoutManagerUser = new LinearLayoutManager(getApplicationContext());
        rvUsers.setLayoutManager(layoutManagerUser);
        userRecyclerAdapter.notifyDataSetChanged();
    }

And of course the SearchView:

 @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);

        MenuItem search = menu.findItem(R.id.action_search);
        SearchView searchView = (SearchView) search.getActionView();

        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {

            @Override
            public boolean onQueryTextSubmit(String query) {
                //Toast.makeText(MainActivity.this, "SEARCH " + query, Toast.LENGTH_LONG).show();
                searchUsers(query);
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                //Toast.makeText(MainActivity.this, "SEARCH " + newText, Toast.LENGTH_LONG).show();
                searchUsers(newText);
                return false;
            }
        });

        return true;
    }
like image 200
Moussa Diallo Avatar answered Oct 15 '22 08:10

Moussa Diallo


My way of searching is rather inefficient as I am using two recyclerviews, one is hidden and the other with the data visible. All data in the document is fetched to an array and I query the array in real-time as you want. The data remains synced always so it seems real-time. Not a good practice but it gets the job done for me. If you need further help I can create a gist for you in that.

The proper way would be to use this official link to search for exactly what you need Full-text search

like image 1
Codedruid13 Avatar answered Oct 15 '22 08:10

Codedruid13