【问题标题】:Processing all existing data of a single collection in Cloud Firestore using Firestore Triggers使用 Firestore 触发器处理 Cloud Firestore 中单个集合的所有现有数据
【发布时间】:2021-07-20 15:16:43
【问题描述】:

在 Firebase RTDB 中,当添加 child_added 侦听器时,它会为每个已经存在的子级调用,如果您想将数据迁移出 Firebase 或进行一些架构迁移,这很方便。我找不到您可以使用 Firestore 触发器执行相同操作的证据。处理 Firestore 集合中所有现有文档和任何新文档的推荐方法是什么?

我可以想到两种方法:

  1. 试试附加 Firestore 触发器是否有效,这样您就可以对某些数据进行实时迁移。
  2. 创建一些手动触发的云函数,该函数迭代集合并为每个集合调用另一个函数。

如果这个问题过于笼统,我们有一个以某种方式结构化的集合,并且需要在某个时候以不同的结构化方式写入 PostgreSQL。

【问题讨论】:

  • 你能解释一下你想要达到的目标吗?
  • 一般来说,我想知道如何处理单个集合中的所有(可能很多)文档。这样做的原因可能是将数据传输到不同的数据库,对现有数据进行非规范化以使其更易于查询,或者例如基于所有现有文档中的某些现有字段添加新字段。
  • child_added 与迁移数据无关,因此有点不清楚。当新数据添加到节点时,该函数会通过事件通知应用程序,以便您采取行动;例如添加了一个新用户,应用程序会收到通知,因此 UI 可以显示新用户。 Firestore 有一个非常相似的函数addSnapshotListener,您可以使用.add、.modified 和.removed 来确定数据发生了什么。它还允许您遍历所有文档。
  • 在 RTDB 中使用child_added,我可以遍历所有现有的和新的对象。但是,是的,这只是客户端而不是函数。我想知道是否有类似的东西,但对于 Cloud Function 和 Firstore。 addSnapshotListener 的链接没有提到监听器也获取现有文档。
  • 查看 Firestore 文档 View changes between snapshots,其中说 重要提示:第​​一个查询快照包含与查询匹配的所有现有文档的添加事件。您当然也可以使用 Cloud 函数迭代文档,但是您想对每个文档做什么?你想导出它还是类似的东西?您不需要云功能 - 只需 addSnapshotListener 即可获取节点,将它们转换为任何内容并保存到磁盘

标签: firebase google-cloud-firestore


【解决方案1】:

在客户端或某些节点进程上,您可以为集合设置观察者,并检查它发生了哪些类型的更改。这是一个例子:

const observer = db.collection('cities')
  .onSnapshot(querySnapshot => {
    querySnapshot.docChanges().forEach(change => {
      if (change.type === 'added') {
        console.log('New city: ', change.doc.data());
      }
      if (change.type === 'modified') {
        console.log('Modified city: ', change.doc.data());
      }
      if (change.type === 'removed') {
        console.log('Removed city: ', change.doc.data());
      }
    });
  });

第一个查询快照包含与查询匹配的所有现有文档的添加事件。

通过使用 Firebase 云功能,您可以使用 onWrite 来了解集合中的每一个变化:

const functions = require('firebase-functions');

exports.myFunction = functions.firestore
  .document('my-collection/{docId}')
  .onWrite((change, context) => { /* ... */ });

如果您只想获取添加的元素,可以使用onCreated 触发器:

exports.createUser = functions.firestore
    .document('users/{userId}')
    .onCreate((snap, context) => {
      // Get an object representing the document
      // e.g. {'name': 'Marie', 'age': 66}
      const newValue = snap.data();

      // access a particular field as you would any JS property
      const name = newValue.name;

      // perform desired operations ...
    });

使用 Firebase 云功能,您只能实时获得关注。集合中已有的所有内容都不会出现在 onCreateonWrite 中,只有当它被更改或删除时。

【讨论】:

  • 这似乎是从客户端或管理 SDK 运行的代码,对吧?这意味着我必须启动一些执行此操作的过程。我有没有办法使用更有效地执行它的云函数来做到这一点?另外,这是否一次加载集合的所有文档?由于可能存在大量现有文档,这不会使 Cloud Function 或 Node.js 进程过载吗?
  • 对不起。我告诉你在客户端搜索东西的地方。我更新了答案并添加了如何使用 Firebase 云功能。
  • 此解决方案的问题是它没有获取现有文档,例如,如果我想向所有现有文档以及在迁移运行时添加的文档添加字段,则需要这样做。
  • 在您写的第一条评论中,您不想获取所有文档,因为它会使 Cloud Function 或 Node.js 进程过载?您能否再解释一下您希望如何运行迁移以及用例是什么。
  • 我担心的是,如果我在一个回调中收到所有文档,那将无法正常工作。我需要以某种方式处理所有文档,现有的和传入的,而不会使执行迁移的任何内容超载。无论是对单个文档多次调用的云函数,还是在服务器上运行的 Node.js 进程。
猜你喜欢
  • 2021-03-27
  • 2021-09-03
  • 2018-03-27
  • 2018-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-09
相关资源
最近更新 更多