user5157625
user5157625

Reputation:

Firebase equalTo doesn't works , tries to get all data

First of all, I know it's common question, but I am really distracted right now, can't really get what I have to do, change schema (which will take too long) or I have some mistake in my code, here is a schema of Firebase nodes, example : enter image description here

here is how I try to query that data :

firebaseDatabase = FirebaseDatabase.getInstance().getReference()
                        .child("Statistic");

        final Query query = firebaseDatabase
                .orderByChild("Programa")
                .equalTo("0010104")
                .limitToFirst(10);


        query.addValueEventListener(new ValueEventListener()
        {
            public void onDataChange(DataSnapshot dataSnapshot)
            {
               for(DataSnapshot s : dataSnapshot.getChildren())
               {
                   Statistic statistic = s.getValue(Statistic.class);
                   Log.d("Found : ",statistic.getFakulteti());
               }
            }

            public void onCancelled(DatabaseError databaseError)
            {
                DialogFactory.errorPrompt(activity).show();
            }
        });

but querying doesn't works, after waiting for like minute or half, it tries to get all the data from Firebase that of course causes outOfmemory exception.

Error Log :

Firebase Database encountered an OutOfMemoryError. You may need to reduce the amount of data you are syncing to the client (e.g. by using queries or syncing a deeper path). See https://firebase.google.com/docs/database/ios/structure-data#best_practices_for_data_structure and https://firebase.google.com/docs/database/android/retrieve-data#filtering_data
                                                                        java.lang.OutOfMemoryError: Failed to allocate a 27113000 byte allocation with 16777216 free bytes and 24MB until OOM
                                                                            at java.lang.StringBuilder.toString(StringBuilder.java:408)
                                                                            at com.google.android.gms.internal.zzaje.toString(Unknown Source)
                                                                            at com.google.android.gms.internal.zzajc.zzsm(Unknown Source)
                                                                            at com.google.android.gms.internal.zzajc.zzso(Unknown Source)
                                                                            at com.google.android.gms.internal.zzajc.zza(Unknown Source)
                                                                            at com.google.android.gms.internal.zzajc$zzc$2.run(Unknown Source)
                                                                            at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)
                                                                            at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                                                                            at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272)
                                                                            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
                                                                            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)

rule i tried :

{
  "rules": {
    ".read": true,
    ".write": false,
      ".indexOn" : ["Programa"]
  }
}

Upvotes: 1

Views: 855

Answers (2)

Bob Snyder
Bob Snyder

Reputation: 38289

If your database contains a very large number of Statistic entries, you should add an index for Programa. Indexing is described here. The presence of an index allows much of the query filtering to occur on the server side and reduces the amount of data transferred to the client.

Your logcat output probably contains a warning like this:

W/PersistentConnection: pc_0 - Using an unspecified index. Consider adding '".indexOn": "Programa"' at Statistic to your security and Firebase Database rules for better performance

The rule for the index must include the path to your data. If Statistic is the root of the path, the rule would be:

{
  "rules": {
    ".read": true,
    ".write": false,
    "Statistic":{
      ".indexOn":"Programa"
    }
  }
}

When the rule is correctly specified, you will not see the warning in logcat about Using an unspecified index. If you continue to see the warning, the rule is not correct.

Upvotes: 1

In your question I can see multiple things... The first one is, your programa key is an String, then if no exists a string value equal to "0010104", don't find anything and if we supose that exists then you get the ten first ones. Is possible this case? If you want to get string key to contains in a part "0010104" then you need yo use startAt() or endAt() instead of equalsTo().

The second one is, how many nodes would contains Statistic node? If your answer is hundred or less (for example), then we can't do anything but if your answer is infinite then is the typical case of firebase, normalize the firebase database, how to do this? Read this post that I answered yesterday about this theme.

Let me know if I have helped you and good programming!

Upvotes: 0

Related Questions