1

I have the following error while I try to query the members of my database:

FirebaseException ([firebase_database/index-not-defined] Index not defined, add ".indexOn": "36a72WVw4weQEoXfk3T9gCtOL9n2", for path "/members", to the rules

I am trying to check if there is already a chat with those members in my database. This is what I am executing:

final snapshot = await _database.ref().child("members").orderByChild(firstUserId).equalTo(true).get();

This is my DB structure

DB

I have been searching how to index by key but I haven't found anything. Is there something I am doing wrong? I hope you can help me thanks in advance.

Dharmaraj
  • 47,845
  • 8
  • 52
  • 84
Joaquín Varela
  • 329
  • 5
  • 18

2 Answers2

1

Indexes for keys are automatically created, but in this case you don't even really need an index as you're not querying on the key.

The easiest way to do this sort of check is:

final snapshot = await _database.ref().child("members").child(firstUserId).get();
if (snapshot.value == true) {
  ...
}

So we're not using a query here, but are instead always reading the snapshot to then check its value.

The reason you can't use a query is that it'd require an explicit/named index on every child node. For more on that, see my answer here: Firebase query if child of child contains a value

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
0

When you're using a structure that looks like this:

Firebase-root
  |
  --- members
       |
       --- -ND81...kyPL
             |
             --- 36a7...L9n2: true
             |
             --- LLhw...vyP2: true

Indeed you need a query since the second level (-ND81...kyPL) inside your database is dynamic. The problem with your approach is that each query you perform requires an index, which cannot be done, since you cannot create an index for each user that becomes a member. Besides that, creating an index cannot be made programmatically. You need to create it manually inside the Firebase console.

It's true that you can attach a listener to the members node and check if a particular UID exists inside the snapshot object that you get as a result. But in my opinion, this solution can be used with a small amount of data. If the number of members gets bigger, downloading the entire node and doing the verification on the client, isn't a recommended option.

Since I think that the member most likely corresponds to a group, an organization, or a user that created them, then most likely it's best to have a node that has a static, known value. So if you're allowed to change the database schema, I would recommend something like this:

Firebase-root
  |
  --- members
       |
       --- $uid
             |
             --- 36a7...L9n2: true
             |
             --- LLhw...vyP2: true

In this way you can simply check if a UID exists using:

final snapshot = await _database.ref().child("members").child(uid).child(firstUserId).get();
if (snapshot.value == true) {
    //Your logic.
}

But the UID node can be any other know ID.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Thank you for answering my question. I cannot understand your solution. having a uid is the same as having any other value. I need to check if a chat already exists before it's created so I will not be having the uid uphand that is why i needed to search for it. – Joaquín Varela Sep 30 '22 at 20:49
  • No, it's not. When you have such a node, `-ND81...kyPL`, it means that is created dynamically when calling the push() method. To be able to check a particular ID for existence, you need to loop over the children to see if it exists or not. If you have a key that you can be known ahead of time, then you can create a reference that can point exactly to that UID. In this way, you'll only download a single child rather than the entire node of UIDs. Does it make any sense now? – Alex Mamo Oct 01 '22 at 08:50