带子集合的Firestore查询 [英] Firestore query with subcollection

查看:79
本文介绍了带子集合的Firestore查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是Firebase的限制还是我做错了所有这些?一切正常,直到我在代码中间添加db.collection('users').doc(friendId).get()...为止.预先感谢.

Is this a limitation to Firebase or am I doing this all wrong? Everything works until I add the db.collection('users').doc(friendId).get()... in the middle of the code. Thanks in advance.

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

friendsList = [];

friendRef.get().then((onSnapshot) => {
    if (!onSnapshot.empty) {
        onSnapshot.forEach((friend) => {

            const friendId = String(friend.data().person_id);

            db.collection('users').doc(friendId).get().then((result) => {
                const firstName = String(result.data().name.first);
                const lastName = String(result.data().name.last);
            })

            const data = {
                personId: friendId,
                firstName: firstName,
                lastName: lastName,
            }

            friendsList.push(data);
        })

        res.send(friendsList);
    } else {
        res.send({
            'message': 'no friends'
        });
    }
}).catch((e) => {
    res.send({
        'error': e
    });
})

推荐答案

数据是从Firestore异步加载的.这意味着,当您将响应发送回客户端时,数据尚未从Firestore加载.

Data is loaded from Firestore asynchronously. This means that by the time you're sending the response back to the client, the data hasn't loaded from Firestore yet.

最简单的方法是使用一些放置良好的日志记录语句:

The easiest way to see this is with some well placed logging statements:

console.log("Before getting friend");
db.collection('users').doc(friendId).get().then((result) => {
  console.log("Got friend");
})
console.log("After getting friend");

仅运行此代码时,它将打印:

When you run just this code it'll print:

交朋友之前

认识朋友后

认识朋友

这可能不是您期望日志进入的顺序.原因是从Firestore返回数据可能需要一些时间.因此,它不会阻塞线程,而是继续运行线程,然后在数据可用时调用回调函数.不幸的是,这意味着您的res.send(friendsList)最终将空列表发送回客户端,因为尚未加载数据.

That is probably not the order you expected the logs to be in. The reason is that the data may take some time to come back from Firestore. So instead of blocking the thread, it continues running the thread and then calls your callback function when the data is available. And that unfortunately means that your res.send(friendsList) ends up sending an empty list back to the client, since the data hasn't loaded yet.

对此的解决方案是使用一堆嵌套的回调,使用Promise.all()或ES6的新async/await关键字.带有promise的代码如下所示:

The solution to this is to use a bunch of nested callbacks, to use Promise.all(), or ES6's new async/await keyword. With promises the code looks like this:

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

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

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

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

因此,我们首先构建所有好友读取操作的列表,然后在完成所有这些操作后,构建响应并将其发送回去.

So we first build a list of all friend read operations, then once all of those are done, we build the response and send it back.

这篇关于带子集合的Firestore查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆