0

I am trying to count the number of children in my DB table that meet a certain condition. If the isSeen column equals false then I want to count that, if it equals true I don't want to count it.

Currently, it's not working but if I change the query from Query query = usersRef.orderByChild("isSeen").equalTo(true); to Query query = usersRef.orderByChild("isSeen"); I get a number but it's not the correct way. Can someone please help me?

Rules:

{   
"rules": {     
  ".read": true,     
    ".write": true,     
      "Messages": {        
          ".indexOn": "isSeen"       
       }     
  }   
} 

"Messages": {
"b3vYlKZFrje0e3wHyBlWIK4ooK93": {
  "DIt5bGqw2WS4eGHNqQJKxZSn3B72": {
    "-N8NCgnwX6V7ghfGlcWS": {
      "dateAdded": 1659337356887,
      "date_time": "Aug-01-2022 3:02:36 AM",
      "from": "DIt5bGqw2WS4eGHNqQJKxZSn3B72",
      "isSeen": true,
      "message": "Yoo",
      "to": "b3vYlKZFrje0e3wHyBlWIK4ooK93",
      "type": "text"
    },
    "-N99iQjlMfeyOM_VCAEB": {
      "dateAdded": 1660184797462,
      "date_time": "Aug-10-2022 10:26:37 PM",
      "from": "DIt5bGqw2WS4eGHNqQJKxZSn3B72",
      "isSeen": true,
      "message": "Wassup",
      "to": "b3vYlKZFrje0e3wHyBlWIK4ooK93",
      "type": "text"
    }
  }
}
},

DatabaseReference usersRef = FirebaseDatabase.getInstance().getReference("Messages");
    Query query = usersRef.child(firebaseUser.getUid()).orderByChild("isSeen").equalTo(true);
    query.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
        @Override
        public void onComplete(@NonNull Task<DataSnapshot> task) {
            if (task.isSuccessful()) {
                long count = task.getResult().getChildrenCount();
                Log.d("TAG1", "count: " + count);
            } else {
                Log.d("TAG2", task.getException().getMessage()); //Never ignore potential errors!
            }
        }
    });

Error message:

D/TAG2: Index not defined, add ".indexOn": "isSeen", for path "/Messages/b3vYlKZFrje0e3wHyBlWIK4ooK93", to the rules

Database schema

His R.H
  • 19
  • 1
  • 5
  • Does your `isSeen` value a boolean? or a string? if the values stored in `isSeen` is a string then you need to use a string value instead of a boolean. `.equalTo("true")` – Marc Anthony B Aug 09 '22 at 01:53
  • It's a boolean @MarcAnthonyB – His R.H Aug 09 '22 at 02:02
  • Do you have any record that has the value of `isSeen` set to true? Please respond using @AlexMamo – Alex Mamo Aug 09 '22 at 08:33
  • No its all false @AlexMamo – His R.H Aug 09 '22 at 11:47
  • If all are false how do you expect to get results? I'm not sure I understand what the problem is. – Alex Mamo Aug 09 '22 at 13:04
  • @AlexMamo It's a messaging system. I'm trying to get the number of messages the user has not seen yet and show it as a notification badge. If `isSeen` is false, then I want to count that as apart of the notifications. If it's true then I don't want to count it because the user already saw that message. – His R.H Aug 09 '22 at 18:20
  • @AlexMamo whenever I add `.equalTo` to this line `Query query = usersRef.orderByChild("isSeen").equalTo("true");` I don't see any results. But if I remove it, then I see results. – His R.H Aug 10 '22 at 04:59

3 Answers3

0

I think you should try this, it working for me. It read your messages for the first time

usersRef.orderByChild("isSeen").equalTo(true).addListenerForSingleValueEvent(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot snapshot) {
     Log.d("TAG", "Count:" + String.valueOf(dataSnapshot.getChildrenCount()));
  }
  @Override
  public void onCancelled(DatabaseError databaseError) {        
  }
});
0

When you're using the following query:

Query query = usersRef.orderByChild("isSeen").equalTo(true);

Firebase will always return the exact data you are querying, meaning that you'll get all elements that have the isSeen field set to true. Please note that there is no way you can query by a negation. So something like this is not possible:

Query query = usersRef.orderByChild("isSeen").notEqualTo(true);
//                                               

According to your comment in which you say that you don't have any elements where the isSeen field is set to true, then your query will yield no results, and that's the expected behavior.

While @TimothyPham's answer will work, using getChildrenCount() might be the best solution. Why? Because if you have a lot of messages this operation requires you to read all of them in order to provide a number. The best solution I can think of would be to increment/decrement a counter as explained in my answer from the following post:

Edit:

Query query = usersRef.orderByChild("isSeen").equalTo(true);
query.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
    @Override
    public void onComplete(@NonNull Task<DataSnapshot> task) {
        if (task.isSuccessful()) {
            long count = task.getResult().getChildrenCount();
            Log.d("TAG", "count: " + count);
        } else {
            Log.d("TAG", task.getException().getMessage()); //Never ignore potential errors!
        }
    }
});

But this code will only work if you have elements in the database that have he isSeen field is set to true.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • I've been trying @TimothyPham's answer all day and still nothing. – His R.H Aug 10 '22 at 22:27
  • Try also my approach. Does it return the number of children where the `isSeen` field is set to `true`? – Alex Mamo Aug 11 '22 at 06:51
  • This `get()` on the add listener line doesn't work for me. I saw it in one of your other answers also and tried it but It didn't work. It shows up red and asks me to rename the reference. – His R.H Aug 11 '22 at 08:29
  • Maybe I'm using a different version of something. – His R.H Aug 11 '22 at 08:30
  • Yes, that's the problem. You aren't using the latest version. Update it and tell me if it works. – Alex Mamo Aug 11 '22 at 08:40
  • I just updated my Android Studio to `Android Studio Chipmunk | 2021.2.1 Patch 2` and i'm still getting the error – His R.H Aug 11 '22 at 09:53
  • It's not about Android Studio, it's about Firebase dependencies that should be updated in the Gradle files. – Alex Mamo Aug 11 '22 at 10:09
  • Ok I updated it and the `get()` problem went away but now I have to update the project to min sdk 19 and compile level 31 – His R.H Aug 11 '22 at 10:20
  • Yes, you should do it. Does it work after you update it? – Alex Mamo Aug 11 '22 at 10:36
  • About 5 more mins it's still updating. – His R.H Aug 11 '22 at 10:39
  • Ok, keep me posted. – Alex Mamo Aug 11 '22 at 10:43
  • No i'm getting this message `D/TAG: Index not defined, add ".indexOn": "isSeen", for path "/Messages", to the rules` – His R.H Aug 11 '22 at 10:51
  • That's the expected behavior. Have you tried adding the index? If not, check [this](https://stackoverflow.com/questions/60848233/what-is-the-correct-way-to-add-indexon-rule-in-firebase-realtime-database) out. Does it work now? – Alex Mamo Aug 11 '22 at 10:52
  • I added it but it still doesn't work `{ "rules": { ".read": true, ".write": true, "Cosmetics": { "Outfits": { ".indexOn": "rarity" } } } }` – His R.H Aug 11 '22 at 10:56
  • I forgot to edit it properly – His R.H Aug 11 '22 at 10:59
  • So is it ok now? Does it work? – Alex Mamo Aug 11 '22 at 11:01
  • No it still show the message above `{ "rules": { ".read": true, ".write": true, "Messages": { "isSeen": { ".indexOn": "rarity" } } } }` – His R.H Aug 11 '22 at 11:01
  • Ok it works but the number is still coming back zero when it should be 2 – His R.H Aug 11 '22 at 11:07
  • So you say that now, you have **two** elements that have the `isSeen` field set to `true`, right? Otherwise, you'll won't get results. – Alex Mamo Aug 11 '22 at 11:08
  • Yeah I set it to true and it showed 0 results. I set it to false and it showed 0 results. – His R.H Aug 11 '22 at 11:10
  • That code in my should definitely work. Maybe there is anything else you're doing wrong. – Alex Mamo Aug 11 '22 at 11:15
  • I don't know I checked it over a few times. – His R.H Aug 11 '22 at 11:17
  • Please edit y our question and add the code you're using **now**, the rules and the database schema if you have changed it. – Alex Mamo Aug 11 '22 at 11:19
  • Just updated it. – His R.H Aug 11 '22 at 11:25
  • It's badly formated. Can you please add a screenshot, or format it properly? I think I what might be. – Alex Mamo Aug 11 '22 at 11:34
  • The rules schema ? – His R.H Aug 11 '22 at 11:36
  • Database schema. – Alex Mamo Aug 11 '22 at 11:39
  • Just updated it. – His R.H Aug 11 '22 at 11:41
  • This is the query that you need `Query query = usersRef.child(firebaseUser.getUid()).chil("DIt5bGqw2WS4eGHNqQJKxZSn3B72").orderByChild("isSeen").equalTo(true);`. There is one child missing. So you need to add it to your reference, right? – Alex Mamo Aug 11 '22 at 11:44
  • I don't think another child is missing but I tried and I'm getting this error now `Index not defined, add ".indexOn": "isSeen", for path "/Messages/b3vYlKZFrje0e3wHyBlWIK4ooK93/b3vYlKZFrje0e3wHyBlWIK4ooK93", to the rules` – His R.H Aug 11 '22 at 11:48
  • Yes, it's missing. You need to have two UIDs in your reference, one of the logged-in user and the other who's chatting with. Yes, in that case, you have to change the rules too. Your issue turns out to be more complex. In the future try to ask separate questions for each issue that you get. – Alex Mamo Aug 11 '22 at 11:52
  • Ok I got it now. So in the rules schema, there's no way to enter the UIDs instead of automatically ? – His R.H Aug 11 '22 at 11:56
  • You always need to have all children when you create a reference. So store them properly so it can be used later. – Alex Mamo Aug 11 '22 at 11:57
-1

Try this:

Log.e(dataSnapshot.getKey(),dataSnapshot.getChildrenCount() + "");
Mises
  • 4,251
  • 2
  • 19
  • 32
CTOFlyFar
  • 106
  • 4