如何在Cloud Firestore查询中加入多个文档?

sar*_*den 14 javascript firebase google-cloud-firestore

我有一个具有以下结构的Cloud Firestore DB:

  • 用户
    • [UID]
      • 名称:"测试用户"
  • 帖子
    • [ID]
      • 内容:"只是一些测试帖."
      • 时间戳:( 2017年12月22日)
      • uid:[uid]

实际DB中存在更多数据,上面仅说明了集合/文档/字段结构.

我在我的网络应用程序中有一个视图,我正在显示帖子,并希望显示发布的用户的名称.我正在使用以下查询来获取帖子:

let loadedPosts = {};
posts = db.collection('posts')
          .orderBy('timestamp', 'desc')
          .limit(3);
posts.get()
.then((docSnaps) => {
  const postDocs = docSnaps.docs;
  for (let i in postDocs) {
    loadedPosts[postDocs[i].id] = postDocs[i].data();
  }
});

// Render loadedPosts later
Run Code Online (Sandbox Code Playgroud)

我想要做的是通过存储在post的uid字段中的uid查询用户对象,并将用户的name字段添加到相应的loadedPosts对象中.如果我一次只加载一个帖子就没问题,只需等待查询返回一个对象,然后在.then()函数中再向用户文档发出查询,依此类推.

但是因为我一次收到多个帖子文档,所以我很难弄清楚如何在调用.get()每个帖子的user/[uid]文档之后将正确的用户映射到正确的帖子,因为他们返回了异步方式.

谁能想到这个问题的优雅解决方案?

Fra*_*len 17

对我来说似乎相当简单:

let loadedPosts = {};
posts = db.collection('posts')
          .orderBy('timestamp', 'desc')
          .limit(3);
posts.get()
.then((docSnaps) => {
  docSnaps.forEach((doc) => {
    loadedPosts[doc.id] = doc.data();
    db.collection('users').child(doc.data().uid).get().then((userDoc) => {
      loadedPosts[doc.id].userName = userDoc.data().name;
    });
  })
});
Run Code Online (Sandbox Code Playgroud)

如果要防止多次加载用户,可以缓存用户数据客户端.在这种情况下,我建议将用户加载代码分解为辅助函数.但它将是上述的变种.


小智 5

我会做1个用户doc调用和所需的帖子调用.

let users = {} ;
let loadedPosts = {};
db.collection('users').get().then((results) => {
  results.forEach((doc) => {
    users[doc.id] = doc.data();
  });
  posts = db.collection('posts').orderBy('timestamp', 'desc').limit(3);
  posts.get().then((docSnaps) => {
    docSnaps.forEach((doc) => {
    loadedPosts[doc.id] = doc.data();
    loadedPosts[doc.id].userName = users[doc.data().uid].name;
  });
}); 
Run Code Online (Sandbox Code Playgroud)

  • 这会加载*all*用户,而不仅仅是撰写过去3个帖子的用户.虽然这在开发过程中可能正常工作,但随着您添加更多用户,您将加载越来越多的不必要数据. (27认同)