【问题标题】:Converting Firebase Database to Cloud Firestore [closed]将 Firebase 数据库转换为 Cloud Firestore [关闭]
【发布时间】:2018-03-20 06:20:42
【问题描述】:

愿你们都得到关于Cloud Firestore by Firebase的好消息。

由于我想将我的 Firebase 数据库 转换为 Cloud Firestore,有什么简单的方法可以转换它吗?

我想继续使用 Cloud Firestore。

【问题讨论】:

    标签: android database firebase firebase-realtime-database google-cloud-firestore


    【解决方案1】:

    当我学习新事物时,我会编写自己的指南。这是我的指南,描述了我如何将实时数据库迁移到 Cloud Firestore。您可以跳过第一部分。我用 Markdown 编写,一些代码标记不能转换为 StackOverflow 的标记。如果您在阅读时遇到问题,我会通过电子邮件将原始 Markdown 版本发送给您。现在我正在努力将我的控制器更新为 Cloud Firestore 查询。

    从 Firebase 实时数据库迁移到 Cloud Firestore

    为什么是 Firebase 实时数据库,为什么不呢?

    两年多来,我的首选堆栈一直是 Angular 和 Firebase。数据绑定引起了我的注意——如果用户更改视图中的数据,控制器和云数据库中的数据会立即更改。或任何其他事件顺序。我的第一个 Firebase 项目是一个井字游戏,两个玩家可以远程玩,我的点击会立即出现在你的屏幕上,反之亦然,云数据库会在两者之间更新。 (Firebase 将此称为“跨客户端实时同步状态。”)

    我也喜欢 Firebase 的 Auth 库。使用 Facebook、Google、Twitter、GitHub 或电话号码或老式电子邮件和密码设置 OAuth2 用户登录非常简单。

    我喜欢不必处理设置和维护服务器。

    而且我喜欢使用 NoSQL 数据库。我在 JavaScript 中使用对象数组,那么为什么不在数据库中使用相同的数据结构呢?

    我不需要这个,但移动应用开发者可以使用 Firebase 实时数据库的离线功能。当用户不在服务范围内时,数据库可以继续更新,这样当用户重新上线时,他或她就可以访问当前数据。

    Plus Firebase 具有存储大型二进制文件(例如图片、音频和视频)的存储空间。

    Firebase 实时数据库有什么不喜欢的地方?查询。我的狗有很多邻居女朋友,我需要一个数据库来跟踪他们。我想打电话给中国的老板,邀请她过来玩。要得到他们的电话号码并不容易。我不能告诉 Firebase 在数组dogs 中查找,找到name 等于China 的对象,然后返回字段phone_number。我必须告诉 Firebase 下载整个数组,然后运行 ​​forEach 循环来遍历每个对象,寻找 name === China。这称为“深度查询”,因为它返回数组中的每个对象、每个子数组以及所有嵌套的子级别。我的狗有很多女朋友,下载都需要几秒钟!

    Firebase 实时数据库具有排序功能,因此我可以下载按姓名、年龄等排序的邻里狗数组。我可以过滤,例如,只有 5 岁以上的狗,但 Firebase 实时数据库无法排序 过滤器。

    在 Firebase 实时数据库中查找特定对象的关键是知道它的键。键是看起来像-KloeQHDC-mugPjJMAG4 的轻量级对象。如果您跟踪对象的键,您可以轻松地从数据库中检索该对象。例如,当一个新用户使用 Facebook 登录并在 Auth 数据库中创建记录,然后您在 Realtime Database 中创建用户帐户时,您可以将用户的 auth 键设置为用户帐户中的键值对,以便您可以轻松找到与该用户关联的身份验证数据(displayNamephotoURL 等)。

    一个数据库用于身份验证,另一个用于二进制文件存储,第三个数据库用于其他一切,您需要跟踪很多键。

    对于大数据项目,Firebase 实时数据库有额外的限制。数据只能嵌套 32 层深。扩大规模需要分片。如果您的客户正在做大数据,或者妄想他的 5000 条记录是大数据,那么您将需要做一些争论来说服您的客户不要在服务器上使用 SQL。

    为什么选择 Cloud Firestore?

    为什么?查询!使用 Cloud Firestore,我现在可以查询我的 dogs 数组,请求 name 等于 China 的记录。 Firebase 只返回我想要的对象。

    Cloud Firestore 可以对数据进行排序过滤。

    Cloud Firestore 可以处理文档中的子集合。您可以请求包含文档子集合的文档,然后只获取该文档,而不需要它的子集合。即浅查询。您甚至可以删除包含文档子集的文档,并保留子集。

    Cloud Firestore 的扩展能力也优于 Firebase 实时数据库。安全性更好,还有其他新功能和改进。

    注入依赖

    首先,您需要将 Cloud Firestore 添加到您的项目中。在链接到 Firebase CDN 后的 index.html 文件中,链接到 Cloud Firestore CDN:

    <script src="https://www.gstatic.com/firebasejs/4.5.0/firebase.js"></script>
    <script src="https://www.gstatic.com/firebasejs/4.5.0/firebase-firestore.js"></script>
    

    或者下载Node模块并链接到它:

    npm install firebase@4.5.0 --save
    

    如果您在 Node 服务器上使用 Firebase SDK,您还需要添加一个依赖项:

    const firebase = require("firebase");
    // Required for side-effects
    require("firebase/firestore");
    

    index.html 中,您还需要初始化应用程序:

    firebase.initializeApp({
      apiKey: '### FIREBASE API KEY ###',
      authDomain: '### FIREBASE AUTH DOMAIN ###',
      projectId: '### CLOUD FIRESTORE PROJECT ID ###'
    });
    

    如果您还使用 Firebase 实时数据库、存储和云消息传递,您将拥有更多内容:

    firebase.initializeApp({
      apiKey: '### FIREBASE API KEY ###',
      authDomain: '### FIREBASE AUTH DOMAIN ###',
      databaseURL: "https://###.firebaseio.com",
      messagingSenderId: "###",
      projectId: '### CLOUD FIRESTORE PROJECT ID ###',
      storageBucket: "###.appspot.com"
    });
    

    最后,在您的控制器中引用 Cloud Firestore:

    var db = firebase.firestore();
    

    迁移您的数据

    接下来,您需要将数据从 Firebase 实时数据库迁移到 Cloud Firestore。这很容易。

    return firebase.database().ref('dogs').once('value') // get a snapshot of the user's data
    .then(function(snapshot) { // then execute a promise on the snapshot
      snapshot.forEach(function(childSnapshot) { // iterate through the user's data
        let childData = childSnapshot.val(); // this is the user's data
        db.collection('dogs').doc(childData.dog).set(childData); // each dog is written to Cloud Firestore
      })
    });
    

    不要这样做:

    return firebase.database().ref('dogs').once('value') // get a snapshot of the user's data
    .then(function(snapshot) { // then execute a promise on the snapshot
        db.collection('dogs').set(snapshot); // copy the array to Cloud Firestore
    });
    

    后者将复制 Firebase 实时数据库密钥。它也不起作用,因为您无法将集合上传到 Cloud Firestore,您只能上传文档。

    在前一个示例中,forEach 循环遍历每条记录并将其作为文档上传到 Cloud Firestore。该集合会自动创建并命名为dogs。这还会移除 Firebase 实时数据库密钥并将其替换为 Cloud Firestore 密钥。

    return 停止执行此命令后的任何代码。如果要迁移多个数组,请仅在最后一个命令上使用return

    firebase.database().ref('dogs').once('value') // get a snapshot of the user's data
    .then(function(snapshot) { // then execute a promise on the snapshot
      snapshot.forEach(function(childSnapshot) { // iterate through the user's data
        let childData = childSnapshot.val(); // this is the user's data
        db.collection('dogs').doc(childData.dog).set(childData); // each dog is written to Cloud Firestore
      })
    });
    
    firebase.database().ref('cats').once('value') // get a snapshot of the user's data
    .then(function(snapshot) { // then execute a promise on the snapshot
      snapshot.forEach(function(childSnapshot) { // iterate through the user's data
        let childData = childSnapshot.val(); // this is the user's data
        db.collection('cats').doc(childData.cat).set(childData); // each cat is written to Cloud Firestore
      })
    });
    
    return firebase.database().ref('cetaceans').once('value') // get a snapshot of the user's data
    .then(function(snapshot) { // then execute a promise on the snapshot
      snapshot.forEach(function(childSnapshot) { // iterate through the user's data
        let childData = childSnapshot.val(); // this is the user's data
        db.collection('cetaceans').doc(childData.cetacean).set(childData); // each whale and dolphin is written to Cloud Firestore
      })
    });
    

    在集合和文档中嵌套数据

    Firebase 实时数据库允许您在数组中拥有数组、在对象中拥有对象、在对象中拥有数组或在数组中拥有对象。 Cloud Firebase 仅允许集合(数组)中的文档(对象)和文档中的集合。也就是说,Cloud Firebase 数据始终是结构化的集合 - 文档 - 集合 - 文档等。

    也许您想将嵌套数组复制到子集合中:

    return firebase.database().ref('dogs').child('girlfriends').once('value') // get a snapshot of the user's data
    .then(function(snapshot) { // then execute a promise on the snapshot
      snapshot.forEach(function(childSnapshot) { // iterate through the user's data
        let childData = childSnapshot.val(); // this is the user's data
        db.collection('dogs').doc(childData.word).set(childData); // write the data to Cloud Firestore
        db.collection('dogs').doc('dogs').collection('girlfriends').doc(childData.dog).set(childData);
    
      })
    });
    

    在这里,我们从数组dogs 中获取数组girlfriends,使用forEach 循环遍历数组,并将每条记录写入集合@ 文档中的集合girlfriends 中的集合@ 中的dogs 987654354@。我将顶级集合和顶级文档都命名为dogs。您可以使用不同的名称。

    更新代码

    现在我们将开始更新我们的代码。

    更新参考

    我们已经更新了一行代码。我们更新了 Firebase 实时数据库参考:

    let ref = firebase.database().ref();
    

    到 Cloud Firestore:

    let db = firebase.firestore();
    

    您可以暂时保留 Firebase 实时数据库参考,然后在我们完成后将其注释掉或删除。

    我有另一个 Firebase 实时数据库参考,指向我的 users 数组:

    let users = firebase.database().ref('users');
    

    我们会将其更新为:

    let usersFS = firebase.firestore().collection('users');
    

    我们将使用不同的名称,以便我们可以一起运行两个数据库,直到我们完成迁移。

    更新查询

    现在我们可以开始更新我们的查询了。在我的控制器中,我的第一个 firebase.database().ref 查询是:

    firebase.database().ref('userLoginEvent').update({'user': user.uid})
    

    对于 Cloud Firestore,我们改为使用:

    db.collection('userLoginEvent').doc('HUSEj7dPh8xsOw32feQY').update({'user': user.uid});
    

    代码几乎相同,只是 Cloud Firestore 需要在集合中指定一个文档。这里我引用了文档的键,因为这个命令总是写入数据库中的相同位置。

    接下来,我有:

    firebase.database().ref('users').child($scope.userAccountKey).update(englishWords);
    

    我们会将其更新为:

    db.collection('users').doc($scope.userAccountKey).update(englishWords);  // this isn't working
    

    市场营销中谁将其命名为 Cloud FireStore?

    这个名字太长了!查找域名,我看到fire.me 仍然可用。我想知道为什么没有市场营销人员建议使用这个简短易记的域名?

    【讨论】:

    • 我同意,显然你不能将火存储在云中。他们只会掉下来。
    • 过时但非常有用的介绍,谢谢!
    【解决方案2】:

    由于数据模型如此不同,因此没有自动的方法来实现这一点。您需要根据应用的需要编写自己的方法。

    documentation 提供了差异的概述。

    【讨论】:

      【解决方案3】:

      这两个数据库有完全不同的数据模型。出于这个原因,目前 firebase 没有提供自动迁移工具,这在很多情况下会导致数据结构效率低下。

      在不久的将来,他们将发布一份指南,详细介绍希望使用 Cloud Firestore 的 RTDB 开发人员的最佳实践,因此请留意!

      源链接 - google firebase group

      Firebase 实时数据库:- 所有 Firebase 实时数据库数据都存储为 JSON 对象。您可以将数据库视为云托管的 JSON 树。与 SQL 数据库不同,没有表或记录。当您将数据添加到 JSON 树时,它会成为现有 JSON 结构中的一个节点,并具有关联的键。您可以提供自己的密钥,例如用户 ID 或语义名称

      Example
      { 
         data: {
                 first: "foo",
                 last: "bar",
                 dob: 1993,
               }
      }
      

      Cloud Firestore:- 在 Cloud Firestore 中,存储单位是文档。文档是包含映射到值的字段的轻量级记录。每个文档都由一个名称标识。 代表用户 alovelace 的文档可能如下所示:

      document
      first : "foo"
      last : "bar"
      dob : 1994
      

      Cloud Firestore 中还有一件事,数据模型存储在 集合和文档,实时数据库没有这样的概念。

      【讨论】:

        猜你喜欢
        • 2021-04-28
        • 2019-07-05
        • 2018-03-15
        • 2018-08-24
        • 2019-08-07
        • 1970-01-01
        • 2020-02-16
        相关资源
        最近更新 更多