How to exclude an element from a Firestore query?

According to the official firestore documentation:-

Cloud Firestore does not support the following type of query:

Queries with a != clause. In this case, you should split the query into a greater-than query and a less-than query. For example, although the query clause where("age", "!=", "30") is not supported, you can get the same result set by combining two queries, one with the clause where("age", "<", "30") and one with the clause where("age", ">", 30).

If you are using FirestoreRecyclerAdapter then FirestoreRecyclerOptions will directly accepts the query using setQuery() method and hence not allows you to perform client side filtering.

If you try to apply filters in onBindViewHolder() while setting the data that might results in empty items in the recycler view. In order to resolve that refer Method 2.

So, the possible solution to your problem would be to create an integer field in your users collection under every document. Eg:-

users [collection]
  - uid [document]
     - uid: "fR5bih7SysccRu2Gu9990TeSSyg2"
     - username: "John"
     - age: 22
     - check: 100

In this I have created a 'check' variable whose value is 100. So, put value of 'check' in all other documents as less than 100. Now, you can easily make a query that finds documents with check<100 as:-

Query q = db.collection("users").whereLessThan("check", 100);

This will retrieve all your documents except the one you don't want. And while setting the data you can set other parameters skipping the check variable.

Method 2 (Client Side Filtering)

We can apply a check in onBindViewHolder() method that if the retrieved uid matches with current user uid then set the height of Recycler view as 0dp. As:-

ViewUserAdapter.java

public class ViewUserAdapter extends FirestoreRecyclerAdapter<User, ViewUserAdapter.ViewUserHolder>
{
    String uid;
    FirebaseAuth auth;

    public ViewUserAdapter(@NonNull FirestoreRecyclerOptions<User> options)
    {
        super(options);
        auth = FirebaseAuth.getInstance();
        uid = auth.getCurrentUser().getUid();
    }

    @Override
    protected void onBindViewHolder(@NonNull ViewUserHolder holder, int position, @NonNull User model)
    {
        DocumentSnapshot snapshot =  getSnapshots().getSnapshot(position);
        String id = snapshot.getId();

        if(uid.equals(id))
        {
            RecyclerView.LayoutParams param = (RecyclerView.LayoutParams)holder.itemView.getLayoutParams();
            param.height = 0;
            param.width = LinearLayout.LayoutParams.MATCH_PARENT;
            holder.itemView.setVisibility(View.VISIBLE);

        }
        else
        {
            holder.tvName.setText(model.name);
            holder.tvEmail.setText(model.email);
            holder.tvAge.setText(String.valueOf(model.age));
        }
    }
}

2021 Update: This Is Supported

Howdy devs. It looks like this is now supported with the where operator used like this: citiesRef.where("capital", "!=", false);


After days and days of struggling with this issue, I finally found the answer. I could not solve this without the help of @Raj. Thank you so much @Raj for the patience and guidance.

First off all, according to the answer provided by @Frank van Puffelen in his answer from this post, I stopped searching for a solution that can help me pass two queries to a single adapter.

In this question, all that I wanted to achieve was to query the database to get all the users except one, me. So because we cannot combine two queries into a single instance, I found that we can combine the result of both queries. So I have created two queries:

FirebaseFirestore db = FirebaseFirestore.getInstance();
Query firstQuery = db.collection("users").whereLessThan("uid", uid);
Query secondQuery = db.collection("users").whereGreaterThan("uid", uid);

I'm having a UserModel (POJO) class for my user object. I found not one, but two ways to solve the problem. The first one would be to query the database to get all user objects that correspond to the first criteria and add them to a list. After that, query the database again and get the other user objects that correspond to the second criteria and add them to the same list. Now I have a list that contains all the users that I need but one, the one with that particular id from the queries. This is the code for future visitors:

firstQuery.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
    @Override
    public void onComplete(@NonNull Task<QuerySnapshot> task) {
        List<UserModel> list = new ArrayList<>();
        if (task.isSuccessful()) {
            for (DocumentSnapshot document : task.getResult()) {
                UserModel userModel = document.toObject(UserModel.class);
                list.add(userModel);
            }

            secondQuery.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if (task.isSuccessful()) {
                        for (DocumentSnapshot document : task.getResult()) {
                            UserModel userModel = document.toObject(UserModel.class);
                            list.add(userModel);
                        }

                        //Use the list of users
                    }
                }
            });
        }
    }
});

The second approach would be much shorter because I use Tasks.whenAllSuccess() like this:

Task firstTask = firstQuery.get();
Task secondTask = secondQuery.get();

Task combinedTask = Tasks.whenAllSuccess(firstTask, secondTask).addOnSuccessListener(new OnSuccessListener<List<Object>>() {
        @Override
        public void onSuccess(List<Object> list) {
            //This is the list that I wanted
        }
});