How can I get the first document ID from a firebase collection, which is not equal to a given ID?

Viewed 1061

I have 'users' collection which contains documents of each user ID. I've also stored the current user's ID in a userID variable using the authenticated user's ID (anonymously signed in).

I need to get one document ID (not the document data) based on a counter of the lowest value (document data item within this collection), and store it in a variable called 'receiverID', but if the document ID equals the current user's ID, then I would like to get the next available ID.

For example, if there are 3 users on my platform (A, B, and C) and the following 'counter' values exist:

  • A: 1, B: 2, C: 3

theoretically, when A queries the collection, they will get their own doc ID back. I would then need to get the second document available within the 'users' collection.

I've begun with the following but am stuck:

receiverID = db.collection('users').orderBy('Questions Received','asc').limit(1)

Also, this is triggered on an event listener (when a user submits a question), so the 'receiverID' must be resolved before the next part of the function. This is what my event listener looks like:

const sayForm = document.querySelector('#say-form');
sayForm.addEventListener('submit', (e) => {
    e.preventDefault();

    db.collection('message').add({
        message: sayForm.sayInput.value,
        time: firebase.firestore.FieldValue.serverTimestamp(),
        sender: userID,
        currentReceiver: receiverID,
        received: 1
    })
    .catch(function(error) {
        console.error("Error adding document: ", error);
    });
});
2 Answers

I was able to solve for it by doing the following:

function getNextReceiver() {
  db.collection('users')
    .orderBy('Messages Received','asc')
    .limit(2)
    .get()
    .then(querySnapshot => {
      let x = querySnapshot.docs[0].id;
      let y = querySnapshot.docs[1].id;
      if (x == userID) {
        receiverID = y
      } else {
        receiverID = x;
      }
    });
    
}

getNextReceiver();

By limiting the search results to 2 and saving them in a variable, I was able to compare against the 'userID' and set the 'receiverID' accordingly as the one that did not match.

There is no different operator for queries in Firestore, so you have to fetch the first document and if it's not the expected documentID fetch the next one and so on. You can do that by doing something like the following:

receiverID = this.getNextReceiver();

function getNextReceiver() {
    db.collection('users')
      .orderBy('Questions Received','asc')
      .limit(1)
      .get()
      .then(function (doc) {
          if(doc.id == userID){
              var validId = false;
              var tempDoc = doc;
              while(!validId){
                  db.collection('users')
                    .orderBy('Questions Received','asc')
                    .startAfter(tempDoc)
                    .limit(1)
                    .get()
                    .then(function (newDoc) {
                        if(newDoc.id != userID){
                            validId = true;
                            return newDoc.id;
                        }
                        tempDoc = newDoc;
                    });
                  
              }
          }
          return doc.id;
      });
}

All this run synchronously. Regarding your submit, it cannot be guaranteed that receiverID will be populated since it is trigger by an event, so you will have to either create a scenario where that value is not populated, or block user interaction until it is populated.

NOTE: All this code is untested but should be a good starting point for you.

Related