11

I'm following the documentation of firestore here and trying to attach a snapshot listener on a collection for getting realtime updates.

I'm having trouble trying to differentiate between whether a response from the Snapshot event listener is a first time response (in which case all the documents in the collection will be returned) or a change event response in which case I want to add the check to identify what change happened. This footnote in the same documentation which goes as :

Important: The first query snapshot contains added events for all existing documents that match the query. This is because you're getting a set of changes that bring your query snapshot current with the initial state of the query

doesn't mention how to identify a first query snapshot with that of subsequent ones.

Only related question I can find on SO is this one but it wouldn't help in my case.

Any help is really appreciated since I've run out of directions to go to.

Thanks.

RmK
  • 1,408
  • 15
  • 28
  • As I understand, every time we opening the activity, it reads all the documents right? after that only modified and removed documents count? – Isuru Bandara Oct 18 '20 at 15:14

3 Answers3

3

Take a careful look at the code in the docs you referenced. It's checking the Type of each DocumentChange object in the QuerySnapshot object:

for (DocumentChange dc : snapshots.getDocumentChanges()) {
    switch (dc.getType()) {
        case ADDED:
            Log.d(TAG, "New city: " + dc.getDocument().getData());
            break;
        case MODIFIED:
            Log.d(TAG, "Modified city: " + dc.getDocument().getData());
            break;
        case REMOVED:
            Log.d(TAG, "Removed city: " + dc.getDocument().getData());
            break;
    }
}

This goes along with the text you cited:

The first query snapshot contains added events for all existing documents that match the query.

You can tell if you've seen a document for the first time because it's an ADDED type of change. MODIFIED and REMOVED type changes are only issued for documents you've seen previously for this listener.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • 2
    Thanks Doug. I was hoping to skip this switch-case check if I know this is the first query snapshot and pass on the entire list using which I can populate the UI. For subsequent calls to the event listener, I was planning to use the checks and consider the document change type etc. Is there somehow this is possible ? – RmK Apr 12 '18 at 14:31
  • 3
    You can certainly maintain your own state within the listener that knows if it's the first time it's been invoked. – Doug Stevenson Apr 12 '18 at 14:35
  • 1
    maybe check this out? https://medium.com/@stle/firebase-firestore-initial-payload-with-onsnapshot-6471c06888c5 – OmomSun Sep 06 '18 at 18:45
  • @OmomSun can you please help me with the same code on Android, I am stuck in the same situation from last 3 days. – Raj Jan 07 '19 at 11:12
  • Hey Doug, how can we achieve this with documentReference rather than collection reference. That is can we use a documentSnapshot in this case – Urchboy Nov 12 '19 at 03:30
  • 1
    How can we differentiate between first ADDED and documents that are ADDED when listening? – Cezar Cobuz Jun 20 '20 at 00:31
0

I'm doing something like this to track the local state

let localCollection = {};

        if(change.type == 'added')
        {
            localCollection[change.doc.ref.id] = change.doc;
        }
        if(change.type == 'modified') {
        let changeObject = {};
        console.log("Before", localCollection[change.doc.ref.id].data());
        changeObject.before = localCollection[change.doc.ref.id];
        changeObject.after = change.doc;
        console.log("After", change.doc.data());
jeber
  • 1
  • 1
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 15 '23 at 08:53
-1

// flag
let flag = false;

collectionRef.onSnapshot((snapshot) => {
snapshot.docChanges().forEach((change) => {

    // NOTE: ctrl first execute
    if (!flag) {
        console.log('not initilized');
        return;
    }

    // anything
    console.log('only after initilized');
}, (err) => {
    console.log(err);
});

// set flag true 
if (!flag) {
    flag = true
    console.log('listener initilized!!');
};
});
  • This corresponds to all notifications except when the listener is set for the first time. Even the first addition notification of a document can be obtained. – おだのぶなが Aug 22 '19 at 06:34
  • 2
    While what you have written may answer the question, however it does seem a little lacking in [explanation](https://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) and may illicit confusion to other users. Can you please expand upon your answer so that it is clearer and more accessible? This will make for better answers and help future users understand how the problem was solved. – Andrew Aug 22 '19 at 13:09