【发布时间】:2018-03-20 06:20:42
【问题描述】:
愿你们都得到关于Cloud Firestore by Firebase的好消息。
由于我想将我的 Firebase 数据库 转换为 Cloud Firestore,有什么简单的方法可以转换它吗?
我想继续使用 Cloud Firestore。
【问题讨论】:
标签: android database firebase firebase-realtime-database google-cloud-firestore
愿你们都得到关于Cloud Firestore by Firebase的好消息。
由于我想将我的 Firebase 数据库 转换为 Cloud Firestore,有什么简单的方法可以转换它吗?
我想继续使用 Cloud Firestore。
【问题讨论】:
标签: android database firebase firebase-realtime-database google-cloud-firestore
当我学习新事物时,我会编写自己的指南。这是我的指南,描述了我如何将实时数据库迁移到 Cloud Firestore。您可以跳过第一部分。我用 Markdown 编写,一些代码标记不能转换为 StackOverflow 的标记。如果您在阅读时遇到问题,我会通过电子邮件将原始 Markdown 版本发送给您。现在我正在努力将我的控制器更新为 Cloud Firestore 查询。
两年多来,我的首选堆栈一直是 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 键设置为用户帐户中的键值对,以便您可以轻松找到与该用户关联的身份验证数据(displayName、photoURL 等)。
一个数据库用于身份验证,另一个用于二进制文件存储,第三个数据库用于其他一切,您需要跟踪很多键。
对于大数据项目,Firebase 实时数据库有额外的限制。数据只能嵌套 32 层深。扩大规模需要分片。如果您的客户正在做大数据,或者妄想他的 5000 条记录是大数据,那么您将需要做一些争论来说服您的客户不要在服务器上使用 SQL。
为什么?查询!使用 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
这个名字太长了!查找域名,我看到fire.me 仍然可用。我想知道为什么没有市场营销人员建议使用这个简短易记的域名?
【讨论】:
由于数据模型如此不同,因此没有自动的方法来实现这一点。您需要根据应用的需要编写自己的方法。
documentation 提供了差异的概述。
【讨论】:
这两个数据库有完全不同的数据模型。出于这个原因,目前 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 中还有一件事,数据模型存储在 集合和文档,实时数据库没有这样的概念。
【讨论】: