LeanCloud 突然宣布停止对外运营,限期一年要求所有用户都迁移走,没有办法只能硬着头皮上了。
看了一些方案后,觉得还是采用开源的 Parse Server 更适合我,因为 LeanCloud 最开始就是模仿这个的,整体使用的方式上手很轻松。
今天第一篇帖子,先写下数据迁移工作,希望能帮助到其他人。
1️⃣ 准备工作
-
前往 LeanCloud 下载 Schema 文件和数据导出的 BSON 文件
-
将所有的 BSON 文件命名都修改。例如你的 Class 是 _User.xXXXX.bson.gz,统一修改格式为 _UserTemp.bson.gz(后续会讲解原因)
2️⃣ Parse Server
-
编写数据库 Schema 文件,建议直接 Clone parse-server-example 项目到本地(Dashboard 需要自行再配置),基础的构建都是准备好的,Schema.ts 文件你可以直接找到。
-
如果你有购买 AI Coding Plan,那么你可以让 AI 帮你读取 LeanCloud 下载的 Schema,并且完善 Parse Server Schema 的编写。
这里有一个坑,你在 Schema 里添加 Class index 时候,如果你某个字段是 Pointer 类型,比如 Notification Class 下有个 user pointer,那么你的索引字段需要是 _p_user,而不是 user。
这是因为 Parse 针对 Pointer 字段,在数据库中字段名必须是 _p_XXX 形式的。
最终的 Schema.ts 大概是这样的:
export const schemaDefinitions = [
{
className: 'LeanCloud Class Name',
fields: {
name: { type: 'String' },
rank: { type: 'Number' },
owner: { type: 'Pointer', targetClass: 'ClassName' },
},
classLevelPermissions: {
find: { '*': true },
count: { '*': true },
get: { '*': true },
update: { '*': true },
create: { '*': true },
delete: { '*': true },
},
indexes: [
{ _p_owner: 1 },
],
}
]
- Schema 编写完成后,那么接下来就是恢复 MongoDB 的 BSON 数据。
执行
mongorestore --gzip --dir ~/Downloads/database/ --db dev
// `~/Downloads/database/` 是你下载并且重命名好的数据文件夹。
// `dev` 是你要恢复的数据库名称。
- 编写脚本。如果你有 TablePlus 这样的软件,可以通过 GUI 界面看到已经恢复的数据,但是类的名称都是 ClassName + Temp 形式的,这样在 Parse Dashboard 还是看不到。
新建一个 js 文件,mongosh 支持执行 js 文件的。
db = connect('mongodb://localhost:27017/dev'); // 确认你的数据库名称
// 获取 class name,更新 Pointer 字段以兼容 Parse Server
// LeanCloud 中 owner Pointer 字段,是个 Object 类型,是 DBRef 格式的。
// 但是在 Parse Server 中,Pointer 类型是 String 类型,并且通过数据库中的字段名结合来判断,必须是 `_p_xxx` 名称,数据格式必须是 `ClassName$id`
// 这段代码的内容是:
// 1. 查询拥有 owner 字段的数据
// 2. 新增 `_p_owner` 字段
// 3. 读取 `owner` 字段,获取 oid,组成新的 `_p_owner` 字段
// 你写一个后,可以让 AI 帮你通过 Schema 文件,按照这个形式,完善其余的 Class 迁移
db.getCollection("NotificationTemp").updateMany(
{ "owner": { "$exists": true } },
[
{
$set: {
"_p_owner": {
$let: {
vars: {
ownerId: { $getField: { field: { $literal: "$id" }, input: "$owner" } }
},
in: {
$cond: [
{ $gt: ["$$ownerId", null] },
{ $concat: ["_User$", { $toString: "$$ownerId" }] },
"$$REMOVE"
]
}
}
},
}
}
]
);
db.getCollection("NotificationTemp").aggregate([
{
"$addFields": {
"_id": { "$toString": "$_id" }, // LeanCloud 使用的 ID 是 ObjectId 类型,Parse Server 需要 String,所以这里做个迁移
}
},
{
"$project": { // 这段是删除不需要的字段
"ACL": 0, // 因为我都是通过 Server 查询数据,所以 LeanCloud 的 ACL 我直接移除了,毕竟客户端也不查数据,后台可以用 master key。
"_w": 0, // _w 和 _r 这 2 个字段会导致 Parse Dashboard 无法正常运行,直接移除,目前也没发现有什么特别用处。
"_r": 0,
"owner": 0, // 迁移完成,不需要了
}
},
{
"$out": "Notification" // 因为 id 从 Object 修改为 String,是不支持在原有表上修改的,所以做一次表的迁移,把 NotificationTemp 迁移到 Notification,完成 id 属性的修改。
// 所以前面针对 BSON 文件做了一次重命名。
}
]).toArray();
db.getCollection("NotificationTemp").drop(); // 删除 NotificationTemp 表
当你完成了所有 Class 的迁移脚本后,运行:
mongosh --file migration.js
建议:
每个 Class 都单独写一个 migration 文件的。
最后放到一个统一的 js 文件中。
load('path/classNameMigration.js')
load('path/classNameMigration.js')
load('path/classNameMigration.js')
load('path/classNameMigration.js')
load('path/classNameMigration.js')
然后执行 mongosh --file all-migration.js,这样方便单独修改某个 class,也方便单独执行某个迁移测试。
经过上述的操作,基本上就可以在本地运行起来,通过 Parse Dashboard 查看你的数据,就像在 LeanCloud Console 查看一样的效果了。