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

查看:34
本文介绍了带有子集合的 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天全站免登陆