将Firebase数据库转换为Cloud Firestore

9

希望大家都能收到Firebase的Cloud Firestore的好消息。

我想把我的Firebase数据库转换成Cloud Firestore,有没有简单的方法可以转换?

我想迁移到Cloud Firestore。

3个回答

23
我学新东西时会写指南。这是我描述如何将我的实时数据库迁移到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实时数据库的离线功能。当用户处于服务范围之外时,数据库可以继续更新,因此当用户重新联机时,他或她可以访问当前数据。
此外,Firebase还具有用于大型二进制文件(例如图片、音频和视频)的存储功能。
那么Firebase实时数据库有什么不好的地方呢?查询。我的狗有很多邻居女友,我需要一个数据库来跟踪它们所有人。我想打电话给China的主人,邀请她过来玩。要获取他们的电话号码并不容易。我不能告诉Firebase查找数组dogs中与name等于China的对象,并返回字段phone_number。我必须告诉Firebase下载整个数组,然后运行forEach循环以迭代每个对象,查找name === China。这被称为“深度查询”,因为它返回数组中的每个对象,每个子数组和所有嵌套的子级。我的狗有很多女朋友,下载所有内容可能需要几秒钟!
Firebase实时数据库具有排序功能,因此我可以按名称、年龄等下载附近狗的数组。我可以进行筛选,例如只有五岁以上的狗,但Firebase实时数据库无法同时进行排序和筛选。
在 Firebase 实时数据库中查找特定对象的关键是要知道它的键。键是轻量级对象,看起来像 -KloeQHDC-mugPjJMAG4。如果你跟踪一个对象的键,你可以轻松地从数据库中检索该对象。例如,当新用户使用 Facebook 登录并在 Auth 数据库中创建记录时,然后在实时数据库中创建用户帐户,你可以将用户的身份验证密钥作为键值对存储在用户帐户中,以便可以轻松地找到与此用户相关联的身份验证数据(displayNamephotoURL 等)。
对于具有 Auth 的一个数据库,二进制文件 Storage 的另一个数据库,以及其他所有内容的第三个数据库,你需要跟踪很多键。
对于大型数据项目,Firebase 实时数据库具有额外的限制。数据只能嵌套 32 层深。扩展需要分片。如果你的客户正在进行大数据处理,或者幻想着他的 5000 条记录就是大数据,你需要一些争论来说服客户不要在服务器上使用 SQL。
为什么选择 Cloud Firestore?
为什么?查询!使用 Cloud Firestore,我现在可以查询我的 dogs 数组,请求名称等于 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中。我将顶级集合和顶级文档都命名为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
我同意,显然你不能把火存储在云中。它们只会掉下来。 - Luke Smith
过时但非常有用的介绍,谢谢! - Geoffrey Hale

1
由于数据模型差异较大,无法自动实现此操作。您需要根据应用程序的需求编写自己的方法。 文档提供了差异的概述。

0

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

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

来源链接 - Google Firebase 群组

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

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

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

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接