-1

Thanks to Frank over at Firebase for helping me with this code. I just had this one issue with pushing the document id under Friends collection. I am not sure what is the best way to push const friendId and const accepted to friendsList array in the code below.

const db = admin.firestore();
const friendRef = 
db.collection('users').doc(id).collection('friends');

friendRef.get().then((onSnapshot) => {
  var promises = [];

  onSnapshot.forEach((friend) => {
    const personId = String(friend.data().person_id);
    const friendId = String(friend.id);
    const accepted = friend.data().accepted;

    promises.push(db.collection('users').doc(personId).get());
  });

  Promise.all(promises).then((snapshots) => {
    friendsList = [];
    snapshots.forEach((result) => {
      friendsList.push({
        friendId: friendId,
        accepted: accepted,
        firstName: result.data().name.first,
        lastName: result.data().name.last,
      });
    });
    res.send(friendsList);
  });
}).catch((e) => {
  res.send({
    'error': e
  });
})

I tried a few things, but it didn't work. Any help would be appreciated.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • What exactly didn't work? Where do you define `friendsList` array? In the code part, where you write `friendId: friendId`, variables `friendId` are not defined. They are left in the block of `onSnapshot.forEach` – Turkhan Badalov Dec 30 '17 at 22:47

2 Answers2

3

The problem is that you push in the promises array what you get from the calls db.collection('users').doc(personId).get() for each friend value. And you never keep values of personId, friendId, accepted for each friend except as local variables.

You should keep them in every array of promises. For this you can return custom Promise like this.

promises.push(new Promise((resolve, reject) => {
    db.collection('users').doc(personId).get()
    .then(docResult => {
        resolve({         
            friendId: friendId,
            accepted: accepted,
            doc: docResult
        });
    })
    .catch(reason => {
        reject(reason);
    });
});

and then when you iterate snapshots array:

snapshots.forEach((result) => {
    friendsList.push({
        friendId: result.friendId,
        accepted: result.accepted,
        firstName: result.doc.data().name.first,
        lastName: result.doc.data().name.last,
    });
});
Turkhan Badalov
  • 845
  • 1
  • 11
  • 17
0

As I also just commented in my answer to your original question, there was a typo in my code there stemming from the confusing variable names.

const db = admin.firestore();
const friendRef = db.collection('users').doc(id).collection('friends');

friendRef.get().then((friendsSnapshot) => {
  var promises = [];

  friendsSnapshot.forEach((friend) => {
    const friendId = String(friend.data().person_id);    
    promises.push(db.collection('users').doc(friendId).get());
  });

  Promise.all(promises).then((friendDocs) => {
    friendsList = [];
    friendDocs.forEach((friendDoc) => {
      friendsList.push({
        personId: friendDoc.id,
        firstName: friendDoc.data().name.first,
        lastName: friendDoc.data().name.last,
      });
    });
    res.send(friendsList);
  });
}).catch((e) => {
  res.send({
    'error': e
  });
})

Since you're looking up the friend's data with doc(friendId), the friendDoc.id in the then() callback will be the ID of each friend.

In cases like this I highly recommend keeping the Cloud Firestore reference documentation handy. For example, in this case I found DocumentSnapshot.id to do what is needed.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thanks Frank, but I went ahead and accepted the answer from @TurkhanBadalov because it provided a way for me to also push `const accepted` to friendsList. –  Dec 31 '17 at 05:32