Firestore:如何使用户和包含用户信息的文档之间的数据保持一致?

Firestore: How to keep data consistent between user and documents that have user information?

总结

我如何在 Firebase 中为我的数据库建模以保持特定页面中的评论更新用户信息,也就是说,如果用户更改其头像或名称,评论也应显示更新的数据用户的。 我大部分时间都使用 MongoDB,使用 Mongoose,现在我正在使用 Firebase 开发移动应用程序。在 Mongo 中,我只会在评论中存储对用户的引用,并填充该字段以从文档中检索我想要的数据。 Firebase 中是否有类似的东西,它甚至是一种好的或可以接受的做法吗?

快速提问

  1. Firebase 中有类似“.populate()”的东西吗?
  2. 我是否应该尽可能多地对文档进行建模以包含将在 view 中使用的数据,并避免 "joins"?

例子

我们有一个用户 collection 和一个有评论的商店 collection。

据我所知,您应该尽量减少文档读取,因此我们应该使用 view 我们需要的特定值来建模我们的数据,以便我们只需要做一个查询。

为了简单起见,假设:

用户有姓名、电子邮件、头像

users: {
    user_id_1: {
        email: "user1@gmail.com",
        name: "John Doe",
        avatar: "some_firestore_url"
    }
}

宜家店铺collection:

  1. 嵌套了 collection 条这样的评论
stores: {
    store_id_1: {
        name: "Dat Cool Store!",
        reviews: {
            user_id_1: {
                name: "John Doe",
                avatar: "some_firestore_url",
                text: "Great store love it!",
                timestamp: "May 07, 2020 at 03:30"
            }
        }
    }
}

我看到的问题是,除非我们使用一个函数用新值更新每个文档中的每个字段,否则没有其他方法可以更新名称和头像中的数据。

  1. 字段中有user_id,查询用户信息后:
stores: {
    store_id_1: {
        name: "Dat Cool Store!",
        reviews: {
            review_id_1: {
                user: "user_id_1",
                text: "Great store love it!",
                timestamp: "May 07, 2020 at 03:30"
            }
        }
    }
}

这是我在 MongoDB 中的模仿方式。

抱歉,如果有些内容听起来令人困惑,或者我没有以最好的方式解释自己,但现在是凌晨 4 点,我只是想把它弄好:)

对我来说,构建 json 集合的方式也取决于数据的大小,我正在尝试存储在集合中。

假设用户数量少,我只想支持 thousand 个用户。所以在那种情况下,我可以采用这种结构。

{
  "store_id_1": {
    "name": "Dat Cool Store!",
    "reviews": [
      {
        "user_id_1": {
          "name": "John Doe",
          "avatar": "some_firestore_url"
        },
        "text": "Great store love it!",
        "timestamp": "May 07, 2020 at 03:30"
      },
      {
        "user_id_2": {
          "name": "John Doe 2",
          "avatar": "some_firestore_url 2"
        },
        "text": "Great store love it! TWO",
        "timestamp": "May 27, 2020 at 03:30"
      }
    ]
  }
}

现在,您可以将所有用户信息嵌入到 stores 集合中。这也会减少您的阅读量。

但如果您想扩展它,那么我建议只存储 users 元数据,然后再从 users 集合中读取。

希望对您有所帮助!

How could I model my database in Firebase to keep, for example, reviews in a specific page updated with the user's info, this is, if a user changes its avatar or name, the reviews should also display the updated data of the user.

在不知道您打算执行的查询的情况下,很难提供可行的架构。我们通常根据要执行的查询构建 Firestore 数据库。

In Mongo I would just store a ref to the user in the review, and populate the field to retrieve the data I wanted from the document. Is there something like this in Firebase, and is it even a good or acceptable practice?

是的,有。根据官方文档,Firestore supported data-types, a DocumentReference 是其中之一,这意味着您只能存储文档的路径,而不是整个文档。在 NoSQL 世界中,重复数据非常普遍,因此在多个地方都有相同的数据。同样,在不知道您的应用程序的用例的情况下,很难说使用规范化是否比仅保留引用更好。为了更好地理解,我建议您从以下 post:

阅读我的回答

并回答您的问题:

  1. Firebase 中有类似“.populate()”的东西吗?

如果您只存储一个 DocumentReference,这并不意味着该引用指向的文档的数据将被自动填充。不,您首先需要从文档中获取引用,然后,根据该引用,您必须执行另一个数据库调用,才能真正从引用的文档中获取数据。

  1. 我是否应该尽可能多地对文档建模以包含将在视图中使用的数据,并避免"joins"?

是的,您应该只存储您实际需要在视图中显示的数据。关于 JOIN 子句,Firestore 不支持这样的东西。一次查询只能获取单个集合中的文档。例如,如果您想从两个集合中获取数据,则至少要执行两个查询。

另一个解决方案是添加第三个集合,其中的数据已经从两个集合中合并,这样您就可以执行单个查询。这已经在上面的 link 中解释过了。

我的回答中解释了一些其他可能有用的信息 post:

在哪里可以找到将数据保存到文档、集合或子集合中的最佳实践。