0

I am trying to access a field labeled vote_count via Cloud Firestore realtime updates.

Below is my data structure:

enter image description here

Previously, under Firebase Realtime Database, I would .addValueEventListener() and drill down to the "answer." However, with Cloud Firestore, it is a bit more complex.

    mStoreSelectedPollRef.addSnapshotListener(new EventListener<DocumentSnapshot>() {
        @Override
        public void onEvent(final DocumentSnapshot documentSnapshot, FirebaseFirestoreException e) {
            if (e != null){
                Log.v("LISTEN", "LISTEN_FAILED");
                return;
            }
            if (documentSnapshot != null){
                Log.v("Current Data", String.valueOf(documentSnapshot.getData()));
                mStoreSelectedPollRef.collection(ANSWERS_LABEL).get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                    @Override
                    public void onComplete(@NonNull Task<QuerySnapshot> task) {
                        updatePollResultAnswersDynamically(task.getResult().size(), documentSnapshot);
                    }
                });
            } else {
                Log.v("Current Data", "Current Data Nulll");
            }
        }
    });

Right now, I am adding a call to .get() within my Snapshot Listener, which seems to be inefficient. I was curious how I would access the:

  1. Total number of answer Documents.
  2. Each individual answer
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
tccpg288
  • 3,242
  • 5
  • 35
  • 80
  • I don't understand the code. It looks like it's saying "every time a certain document changes, query all the documents in the answers collection, count them, then do something with the first document". If you want to maintain a document count without having to pull an entire collection, there is a pattern for that. https://firebase.google.com/docs/firestore/solutions/counters – Doug Stevenson Feb 22 '18 at 03:23
  • I essentially want to query the answers and get the size of the answers. Then i want to access the individual fields within each answer. In order to do this, it appears I need to have both .addSnapshotListener and .addOnCompleteListener(). Trying to figure out if there is a way to simplify – tccpg288 Feb 22 '18 at 03:25
  • OK, I'm confused. You have mStoreSelectedPollRef and you're essentially querying it twice, once for incremental changes, and again for size and content? – Doug Stevenson Feb 22 '18 at 03:27
  • I guess I could add my .addSnapshotListener() to my answers node, but again I am not sure if the DocumentSnapshot it returns will give me the data I need – tccpg288 Feb 22 '18 at 03:30
  • I don't think you need a snapshot listener at all. Just query the entire collection once with get(), iterate the documents in it, and do what you want with each of them. – Doug Stevenson Feb 22 '18 at 03:31
  • .get() is not for realtime updates, as far as I can tell https://firebase.google.com/docs/firestore/query-data/listen – tccpg288 Feb 22 '18 at 03:34
  • Querying the entire collection every time one thing in it changes is neither typical nor efficient. But if that's what you need, then so be it. – Doug Stevenson Feb 22 '18 at 03:36
  • Possible duplicate of [get CollectionReference count](https://stackoverflow.com/questions/48534676/get-collectionreference-count) – Alex Mamo Feb 22 '18 at 08:29

1 Answers1

0

Given this snippet:

mStoreSelectedPollRef.collection(ANSWERS_LABEL).get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
    @Override
    public void onComplete(@NonNull Task<QuerySnapshot> task) {
        updatePollResultAnswersDynamically(task.getResult().size(), documentSnapshot);
    }
});

You can get the total number of answer documents with:

task.getResult().size()

Since you already have this code, I'm not really sure what you're asking. If you're asking if there is a way to get the count without getting the documents, look here: https://stackoverflow.com/a/46555026

To access the individual answer documents, you loop over the query snapshot:

for (DocumentSnapshot document : task.getResult()) {
    Log.d(TAG, document.getId() + " => " + document.getData());
}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thanks Frank, I have .addSnapshotListener() and .addOnCompleteListener(). It seems a bit redundant, but the QuerySnapshot appears to offer more data than a DocumentSnapshot. Just wondering if this approach is conventional or if I am creating unnecessary code – tccpg288 Feb 22 '18 at 03:26
  • 1
    You call `addSnapshotListener` on the `QcU...` document, you call `get()` on its `answers` collection. If both are needed that is indeed the right way to load them. – Frank van Puffelen Feb 22 '18 at 03:34
  • Got it - essentially, I am trying to use realtime updates. The .addSnapshotListener() does not have the .size() method which is why I am essentially nesting another .get() method. My understanding is realtime updates are activated only under .addSnapshotListener() – tccpg288 Feb 22 '18 at 03:39
  • `addSnapshotListener` gets a single snapshot. Its size would always be `1`. Keep in mind: when you load a document, its nested collections are not automatically loaded. – Frank van Puffelen Feb 22 '18 at 04:54
  • Got it, so in other words, there is no issue calling .get() afterward. I am trying to compare it to the realtime database, where you can add the listener, drill down into the nodes of that listener, .getChildrenCount(), and others. It doesn't mirror it completely when I was first trying to replicate every method – tccpg288 Feb 22 '18 at 14:20
  • In this case the difference is quite intentional: reads in Firestore are shallow, they don't read subcollections. If you want all data in one read, consider if the answers shouldn't actually be nested/sub-fields in the same document (instead of a subcollection). – Frank van Puffelen Feb 22 '18 at 15:12
  • Got it - so it may be a hint that I should restructure the data and maybe even create a separate answers node – tccpg288 Feb 22 '18 at 15:18