• 6
name

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191

Backtrace:

File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

name Punditsdkoslkdosdkoskdo

Firestore not querying second collection

I'm kind of new to android studio and firestore database and I'm having some trouble with querying my second firestore collection. As the title says, i am querying two collections, first one is:

enter image description here

with the code :

    firestore = FirebaseFirestore.getInstance();
    FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
            .build();
    firestore.setFirestoreSettings(settings);
    firestore.collection("Obiective").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if (task.isSuccessful()) {

            //<--------- Check if firestore entry is already downloaded into file --------->
            SingletonObjectivesId.getInstance().getIds().clear();
            for (QueryDocumentSnapshot document : task.getResult()) {
                Log.d(TAG, task.getResult().size() + " number of documents");
                SingletonObjectivesId.getInstance().setSize(task.getResult().size());

                if(document.exists() && document != null) { ...

and the second collection have the following format:

enter image description here

with the code:

        firestore.collection("Routes")
            .get()
            .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if (task.isSuccessful()) {

                        Log.d(TAG, task.getResult().size() + " = task.getResult().size()");

                        for (QueryDocumentSnapshot document : task.getResult()) {
                            objectives_id.clear();
                            id_route = document.getId();

                            if(document.exists() && document != null) {
                                Map<String, Object> map = document.getData();
                                for (Map.Entry<String, Object> entry : map.entrySet()) {
                                    String field_name = entry.getKey() + "";
                                    String id = document.getString(field_name) + "";
                                    objectives_id.add(id);
                                }
                            }
                            routes.add(new Route(objectives, objectives_id, id_route));
                        }
                    } else {
                        Log.d(TAG, "Error getting documents: ", task.getException());
                    }
                }
            });

As you can see in the second code i added a Log.d ( after if (task.isSuccessful()) ) who will display the number of documents. In my case, the first query Log.d returns 3 and the second returns 0 despite the fact that i have 2 documents in there. How can i access this 2 documents ?

Thank you.

Firebase APIs are asynchronous, meaning that the onComplete() method returns immediately after it's invoked, and the callback from the Task it returns, will be called some time later. There are no guarantees about how long it will take. So it may take from a few hundred milliseconds to a few seconds before that data is available. Because that method returns immediately, the number of documents that you try to log, is not populated from the callback yet.

Basically, you're trying to use a value synchronously from an API that's asynchronous. That's not a good idea. You should handle the APIs asynchronously as intended.

A quick solve for this problem would be to move the code that queries the second collection inside the first callback (inside the onComplete() method) so-called nested queries, otherwise I recommend you see the last part of my anwser from this post in which I have explained how it can be done using a custom callback. You can also take a look at this video for a better understanding.

  • 1
Reply Report
      • 1
    • Thank you for the fast asnwer. I will read the links that you gave me and try to better understand how firebase works. Thank again.
      • 2
    • Hi, i just edited my code after i watched the video and i still have the same problem. At least now the querying is made in the right order, but the second one still have no items, Log.d(TAG, task.getResult().size()) still returns 0.
    • I guess is might be something related to the object on which you calling the methods but without seeing your new code, I cannot be much of a help.
      • 1
    • Ok, i will do this, but until then i noticed that even my first collection is not queried correctly. I updated it with one more entry (document) as a test and it seems that the new entry is not seen. May the problem be somewhere else, not in my code ?

After i followed the steps from the video, i updated the code like this:

I have a global variable firestore created at the beginning of my class

private FirebaseFirestore firestore;

I have two methods readDataObjective and readDataRoute and two interfaces FirestoreCallback and FirestoreCallbackRoutes

readDataRoutes

    private void readDataRoute(FirestoreCallbackRoute firestoreCallbackRoute){
    firestore.collection("Trasee").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if (task.isSuccessful()) {
                        for (QueryDocumentSnapshot document : task.getResult()) { ...

readDataObjective

   private void readDataObjective(FirestoreCallback firestoreCallback){
    firestore.collection("Obiective").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if (task.isSuccessful()) {   
                SingletonObjectivesId.getInstance().getIds().clear();
                for (QueryDocumentSnapshot document : task.getResult()) { ...

Interfaces

private interface FirestoreCallback{
    void onCallback(ArrayList<Objective> list);
}

private interface FirestoreCallbackRoute{
    void onCallback(ArrayList<Route> list);
}

And in onCreate method i call readDataObjective and readDataRoute like this

firestore = FirebaseFirestore.getInstance();
    FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder().build();
    firestore.setFirestoreSettings(settings);

    readDataObjective(new FirestoreCallback() {
        @Override
        public void onCallback(ArrayList<Objective> list) {
            for(Objective item : list){
                //Create plainText Object - delimiter "/~/"
                String data = "Title:" + item.getTitle() + "/~/" +

............................

     } else if(str.contains("Longitude:")){
                            obj.setLongitude(str.substring(10,str.length()));
                        }

                        start = crt + 2;
                    }
                }
                SingletonObjectivesArray.getInstance().getObjectives().add(obj);
            }

            readDataRoute(new FirestoreCallbackRoute() {
                @Override
                public void onCallback(ArrayList<Route> list) {
                    Log.d(TAG, 2 + " ");
                    ArrayList<Objective> routeObjectives = new ArrayList<>();

                    for (int i = 0; i < list.size(); i++) {
                        routeObjectives.clear();
                        for (int j = 0; j < SingletonObjectivesArray.getInstance().getObjectives().size(); j++){ ...

With the mention that readDataRoute is called inside readDataObjective, at the end of it.

I noticed that the problem is not only with the second query, but with the first one too. I added a new document into the first collection and after running the code, the first query return the old data ( without my new entry ).

  • 0
Reply Report