将 Firebase 数据库转换为 Cloud Firestore

Converting Firebase Database to Cloud Firestore

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

因为我想将我的 Firebase 数据库 转换为 Cloud Firestore 是否有任何简单的转换方法?

我想继续使用 Cloud Firestore。

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

documentation 提供了差异的概述。

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

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

来源link - 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

One more thing in cloud firestore, the data model are stored into collection and document, and Realtime Database has no such concepts.

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

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

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

两年多来,我的首选堆栈一直是 Angular 和 Firebase。数据绑定引起了我的注意——如果用户在视图中更改数据,控制器和云数据库中的数据会立即发生变化。或任何其他事件顺序。我的第一个 Firebase 项目是一个井字游戏,两个玩家可以远程玩,我的点击会立即出现在你的屏幕上,反之亦然,云数据库会在两者之间更新。 (Firebase 称之为 "synced states across clients in realtime.")

我也喜欢 Firebase 的 Auth 库。使用 Facebook、Google、Twitter、GitHub 或 phone 号码或老式电子邮件和密码设置 OAuth2 用户登录很容易。

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

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

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

Plus Firebase 可以存储大型二进制文件,例如图片、音频和视频。

为什么不喜欢 Firebase 实时数据库?查询。我的狗有很多邻居女朋友,我需要一个数据库来跟踪她们。我想打电话给中国老板请她过来玩玩。要获得他们的 phone 号码并不容易。我无法告诉 Firebase 查看数组 dogs,找到 name 等于 China 的对象,以及 return 字段 phone_number。我必须告诉 Firebase 下载整个数组,然后 运行 一个 forEach 循环遍历每个对象,寻找 name === China。这被称为 "deep query" 因为它 return 数组中的每个对象,每个子数组,以及所有嵌套的子级别。我家狗的女朋友多得要秒才能全部下载!

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

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

一个数据库用于 Auth,另一个数据库用于二进制文件存储,第三个数据库用于其他一切,您有很多密钥需要跟踪。

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

为什么选择 Cloud Firestore?

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

Cloud Firestore 可以排序 过滤数据。

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

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

注入依赖关系

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

<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>

或者下载节点模块并link到它:

npm install firebase@4.5.0 --save

如果您在节点服务器上使用 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 中的文档 dogs 中。我将 top collection 和 top document 都命名为 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 仍然可用。我想知道为什么没有营销人员建议使用简短、好记的域名?