Cloud Firestore:如何在我的集合查询中获取文档引用并将其映射为JSON值?

Mau*_*lva 9 cloud ref firebase google-cloud-firestore

假设我收集了一些评论.每个评论对象都有一个"doc ref"给发布的用户.我需要一个查询,它将返回一个注释列表,包括每个用户引用的值,所以我的查询返回一个很好的格式化的Json注释对象.

use*_*453 12

这里有一个类似的问题.什么是firestore参考数据类型有用?,根据这个答案/sf/answers/3259908361/,我认为不可能做你要问的事.

你必须自己加载每个引用,例如

const comments = []
firebase.firestore().collection('/comments').get().then(snapshot => {
  snapshot.docs.forEach(doc => {
    const comment = doc.data()
    comment.userRef.get().then(snap => {
      comment.user = snap.data()
      comments.push(comment)
    })
  })
})
Run Code Online (Sandbox Code Playgroud)

对于许多评论,这将增加很多开销.也许你可以在服务器端编写一个为你们所有人工作的CloudFunction,并返回一个格式化的JSON.

看起来他们可能会在未来继续支持这项工作:https://stackoverflow.com/a/46614683/473453


Cha*_*tin 7

我建议您在每个评论中复制用户数据。在评论文档中创建一个字段,该字段是一个命名的对象,user并提供显示评论所需的最少信息量。所以你的comment文档可能看起来像...

{
  id: 'CEXwQAHpk61vC0ulSdZy',
  text: 'This is a comment',
  user: {
    id: 'd5O4jTsLZHXmD1VJXwoE,
    name: 'Charlie Martin',
    avatar: 'https://...'
  }
}
Run Code Online (Sandbox Code Playgroud)

现在,您拥有了显示评论所需的一切。如果有人点击评论的作者,您就可以获取该 ID 并使用它来加载评论者的完整个人资料。

关系数据库中的数据重复是不受欢迎的,因为它们是为使用外键处理这些场景而构建的。

然而,在像 firestore 这样的 NoSQL 数据库中,实际上鼓励重复数据以简化查询并减少通过网络发送的数据量。

如果您user为每条评论加载了完整文档,那么您加载的用户信息可能比显示评论所需的信息多得多。

  • 好吧,我认为这笔交易的规模更大;) 我点击了“乔”,然后突然我看到了某个鲍勃的个人资料——我变成了一个真正困惑的用户:“我的手指这么胖吗?我的视力是不是模糊了? 我很确定我想查看 Joe 的个人资料,这是一个我从未听说过的 Bob...” 根据我的经验,普通用户不了解软件和数据库 - 他们只知道该应用程序无法运行正如他们所期望的那样 (22认同)
  • 现在回想起来,这真的很奇怪。在这种情况下,我会编写一个云函数,在更新用户记录时更新所有重复的数据 (14认同)
  • 请注意,使用这种方法,您将获得过时的数据,例如,如果用户更改其用户名(除非每次用户更新时,您都会更新其所有出现的内容) (9认同)
  • @CharlieMartin我认为这是正确的方法。我认为偶尔更新其他地方的用户记录比多次阅读文档更好且成本更低 (2认同)

Chr*_*ich 5

这也让我很恼火。我制作了一个实用程序助手,可以自动填充第一级。

帮手

import { get, set } from 'lodash'

const getReference = async documentReference => {
  const res = await documentReference.get()
  const data = res.data()

  if (data && documentReference.id) {
    data.uid = documentReference.id
  }

  return data
}

const hydrate = async (document, paths = []) => Promise.all(
    paths.map(async path => {
      const documentReference = get(document, path)

      if (!documentReference || !documentReference.path) {
        return console.warn(
          `Error hydrating documentReference for path "${path}": Not found or invalid reference`
        )
      }

      const result = await getReference(documentReference)
      set(document, path, result)
    })
  )
}

export { hydrate }
Run Code Online (Sandbox Code Playgroud)

用法示例:

getUser = async uid => {
  return this.db
    .collection('users')
    .doc(uid)
    .get()
    .then(async documentSnapshot => {
      const data = documentSnapshot.data()
      await hydrate(data, ['company', 'someOtherNestedRef-2', 'someOtherNestedRef-1'])
      return data
    })
}
Run Code Online (Sandbox Code Playgroud)

限制:此示例不适用于深层嵌套引用


归档时间:

查看次数:

27144 次

最近记录:

6 年,1 月 前