当前位置: 首页 > 知识库问答 >
问题:

将嵌套数据从实时数据库迁移到FiRecovery

融泓
2023-03-14

我正在将Firebase实时数据库迁移到Firestore,并且我有嵌套数据

我有嵌套数据,我想从中创建一个集合。

示例:

"data" : {
  "-LYBzlXPoN0137KRLovk" : {
    "-LYC-HHqDFgL9PovJiBr" : {
      "age" : 35,
      "country" : "Country",
      "date" : "2019-02-08T13:07:10+01:00",
      "gender" : "male",
      "id" : 1549627467620,
    },
    "age" : 35,
    "country" : "Country",
    "date" : "2019-02-08T13:04:27+01:00",
    "gender" : "male",
    "id" : 1549627467620,

我想从FiRecovery中的嵌套数组创建一个子集合。因此我尝试了以下方法(Cloud Function):

exports.migrateVisits = functions.database.ref('/data/{key}/{nestedKey}')
    .onWrite((change:any, context:any) => {
        // Get a reference to the Firestore document of the changed user
        let userDoc = admin.firestore()
            .collection(`data/{key}/nestedKeys`)
            .doc(context.params.nestedKey);
        // If this user has been deleted, delete in Firestore also
        if (!change.after.exists()) {
            return userDoc.delete();
        }
        // Get the user object with the new changes,
        // as opposed to its value before the edit
        let userData = change.after.val();
        // Now update Firestore with that change

        return userDoc.set(userData);
    });

但我得到了错误:错误:参数“数据”不是有效的文档。输入不是普通的JavaScript对象。

您有没有想过以最好的方式迁移嵌套的子数据?

雷诺更新

exports.migrateVisits = functions.database.ref('/data/users/{userId}/visits/{visit}')
    .onWrite((change:any, context:any) => {
        let userData = change.after.val();
        const mainDocObj:any = {};

        let batch = admin.firestore().batch();

        Object.keys(userData).forEach(e => {
            console.log(e);
            if (
                e == 'age' ||
                e == 'country' ||
                e == 'date' ||
                e == 'gender' ||
                e == 'id' ||
                e == 'lastVisit' ||
                e == 'magazineRoute' ||
                e == 'magazineRouteDone' ||
                e == 'magazineRouteLastDate' ||
                e == 'name' ||
                e == 'notice' ||
                e == 'onNextVisit' ||
                e == 'pause' ||
                e == 'placements' ||
                e == 'plz' ||
                e == 'street' ||
                e == 'tag' ||
                e == 'type'
            ) {  //here, add the other main keys, e.g. with ['gender', 'age', 'country', ....].includes(e)
                mainDocObj[e] = userData[e];
            } else {
                //it needs to be added as a doc in the sub-collection
                const subDocRef = admin
                    .firestore()
                    .collection(`users/${context.params.userId}/vi/${context.params.visit}/rv`)
                    .doc(e);
                batch.set(subDocRef, userData[e]);
            }
        });

        //We first write the mainDoc
        console.log(mainDocObj);
        return admin
            .firestore()
            .collection(`users/${context.params.userId}/vi`)
            .doc(context.params.visit)
            .set(mainDocObj)
            .then(() => {
                //We then write the children in one batch
                return batch.commit();
            });
    });

共有1个答案

徐昆
2023-03-14

以下应该可以做到:

exports.migrateVisits = functions.database.ref('/data/{key}/{nestedKey}')
    .onWrite((change:any, context:any) => {
        // Get a reference to the Firestore document of the changed user

        const key = context.params.key;

        const userDoc = admin
          .firestore()
          .collection('data/' + key + '/nestedKeys')              
          .doc(context.params.nestedKey);

        // If this user has been deleted, delete in Firestore also
        if (!change.after.exists()) {
            return userDoc.delete();
        }
        // Get the user object with the new changes,
        // as opposed to its value before the edit
        let userData = change.after.val();
        // Now update Firestore with that change

        return userDoc.set(userData);
    });

您必须使用上下文。params可获取路径的值。

根据我们的评论进行更新。

需要注意的主要一点是,由于我们现在在/data/{key}级别进行侦听,因此必须区分属于主文档的数据和属于子文档的数据。在下面的代码中,我建议根据数据名称(性别、日期、年龄、id…)进行此操作。如果在循环过程中,您遇到具有其他名称的数据项(例如id,如LYC-HHqDFgL9PovJiBr),则表示该数据项是子文档。

另一点需要注意的是使用批处理写入,请参阅https://firebase.google.com/docs/firestore/manage-data/transactions#batched-writes

此外,我让您负责检查是否在not上删除了文档。您可能需要调整的另一个方面是对已经存在的孩子的管理,如果您修改了节点下的年龄,例如LYC-HHqDFgL9PovJiBr,因为在这种情况下,触发器仍将发生在/数据/{键}级别。

exports.migrateVisits = functions.database
  .ref('/data/{key}')
  .onWrite((change:any, context:any) => {
    const key = context.params.key;
    let userData = change.after.val();
    const mainDocObj = {};

    let batch = admin.firestore().batch();

    Object.keys(userData).forEach(e => {
      if (e === 'gender') {  //here, add the other main keys, e.g. with ['gender', 'age', 'country', ....].includes(e)
        mainDocObj[e] = userData[e];
      } else {
        //it needs to be added as a doc in the sub-collection
        const subDocRef = admin
          .firestore()
          .collection('data/' + key + '/nestedKeys')
          .doc(e);
        batch.set(subDocRef, userData[e]);
      }
    });

    //We first write the mainDoc
    return admin
      .firestore()
      .collection('data')
      .doc(key)
      .set(mainDocObj)
      .then(() => {
        //We then write the children in one batch
        return batch.commit();
      });
  });

 类似资料:
  • 我正在寻找最好的方法来迁移我的应用程序数据库,它使用firebase实时数据库到新的云Firestore数据库。对于我正在进行的项目,我确信我不需要做任何数据模式的更改,所以我几乎只是尝试1-1映射它。Firebase在他们的网站上建议只编写一个脚本来实现这一点,但我不确定最好的方法。有没有人已经做了一个脚本来完成这件事?

  • move key db-index 返回1成功。0 如果key不存在,或者已经在指定数据库中

  • 问题内容: 将Solr核心迁移到elasticsearch索引的最佳方法是什么? 不推荐使用solr-river-plugin(https://github.com/javanna/elasticsearch-river- solr )。 问题答案: OpenSource Connections中有一个不错的,由爱心人士精心制作的自定义Python工具,您可以用来执行以下操作: https://g

  • 问题内容: 我有一个现有的PHP / MySQL应用程序,我正尝试将其迁移到AngularJS / Firebase,以作为学习这些较新技术的一种方式。 该应用程序在MySQL中具有自己的表架构。一个这样的表如下所示: 我的问题是:如何将这个表结构及其中的数据从MySQL迁移到Firebase? 我尝试通过查询将数据导出到JSON字符串中,例如: 这给出了有效的JSON字符串,例如: 我将其保存在

  • 问题内容: 我正在使用Java开发数据库迁移工具。该工具将数据库表及其数据复制到目标数据库。但是我希望它可以在不同的数据库上工作。从mysql复制并在derby等中创建。使用JDBC,我们可以收集有关表及其列的足够信息。但是我要问的是,是否可以使用sql free在Java上重新创建表。我的意思是不同的数据库具有不同的数据类型,有时它们在sql语法上也有所不同。那么JDBC或任何其他库(可以是开放

  • 在开发和维护一个数据库驱动的应用程序时, 数据库的结构会像代码一样不断演变。 例如,在开发应用程序的过程中,会增加一张新表且必须得加进来; 在应用程序被部署到生产环境后,需要建立一个索引来提高查询的性能等等。 因为一个数据库结构发生改变的时候源代码也经常会需要做出改变, Yii 提供了一个 数据库迁移 功能,该功能可以记录数据库的变化, 以便使数据库和源代码一起受版本控制。 如下的步骤向我们展示了