此寄存器包含非官方模式、样本代码或工具,以帮助开发者更有效地构建 动物全部数据 动物实验室 储存库是“现成的”,没有支持。 通过使用此寄存器或其内容,您同意此寄存器可能永远不会被正式支持并移动到 动物组织。 。 。 .
动物 Schema 迁移
导言
目标
France Schema Migrate工具是一个有观点的工具,有三个目标:
- 将动物资源设置为代码.
- 支持较大队伍的防故障计划迁移.
- 就如何管理动物资源提供指导,方法是显示可以生成的Let语句,以进行交易更新数据库.
什么是“Schema”迁移?
Schema是个令人困惑的名字 但通常我们在找这种东西 功能、收藏、索引、作用和获取者等动物资源被认为是一种计划。 虽然 数据迁移 这也是一个非常不同的问题,请参看关于数据迁移的章节,了解更多信息.
设置
将工具安装在安装了动物标记驱动程序的数据库中。 Javascript驱动程序是同级依赖,因此不会被工具拉入. 依靠与寄存器相同的动物驱动器让用户控制该版本更有意义.
npm install @fauna-labs/fauna-schema-migrate
与 npx 交互运行 :
npx fauna-schema-migrate run
或与:
node_modules/.bin/fauna-schema-migrate
这个 最低 驱动程序版本应为:
"faunadb": "^4.0.3"
此驱动程序包含一些FQL格式化的次要修正,这是工具正常工作所需的.
可用命令
运行 npx fauna-schema-migrate 以查看所有命令和额外选项.
Commands:
run Run interactively
init Initializing folders and config
state Get the current state of cloud and local migrations
generate Generate migration from your resources
rollback [amount] [childDb...] Rollback applied migrations in the database
apply [amount] [childDb...] Apply unapplied migrations against the database
或运行 npx fauna-schema-migrate run 进行互动测试 所有命令都可以通过使用运行进行交互运行. 从回滚到应用的命令参数虽然(尚未)无法交互访问.
流动
-
初始化 标准文件夹 与
npx fauna-schema-migrate init或使用交互式run命令.将生成一个 动物 文件夹和 a .fauna-migrate.js (法语) 配置文件 。 如果您不想更改默认文件夹或默认收藏以存储迁移状态,可以去除.fauna-migrate.js文件.
由 init 生成的默认文件夹结构如下 :
fauna > resources > migrations -
写入资源
通过添加 .fql 或.js 文件并默认导出到 动物 > 资源文件夹来创建资源。 任何文件,即使是子文件夹中的文件,都会被工具取出,以便您可以按自己的意愿组织文件. 例如,您可以组织文件如下:
fauna > resources > users_collection.fql > users_by_name_index.fql > logged_in_users_role.fql或按资源类型或域使用文件夹和顺序 :
fauna > resources > collections > users.fql > indexes > users_by_name.fql > roles > logged_in_users.fql这无关紧要,只有一个提醒,那就是要避免文件夹名'dbs',除非另作配置,因为这个名称是用来支持儿童数据库迁移的。 资源文件总是必须包含以下功能中的一个(而只有一个).
CreateCollection(...) CreateIndex(...) CreateFunction(...) CreateRole(...) CreateAccessProvider(...)例如,以下内容是有效的 .fql 时间 文件 :
CreateIndex({ name: 'users_by_alias', source: Collection('users'), terms: [ { field: ['data', 'alias'], }, ], unique: true, serialized: true, })使用时 .js (英语) 文件中,只要默认导出为上列之一,就可以导入/写入您想要的任何文件。 以下是来自Fwitter的一个基于外部文件创建函数的例子:
import faunadb from 'faunadb' import { CreateFweet } from '../fauna/src/fweets' const q = faunadb.query const { CreateFunction, Query, Var, Lambda, Role } = q export default CreateFunction({ name: 'create_fweet', body: Query(Lambda(['message', 'hashtags', 'asset'], CreateFweet(Var('message'), Var('hashtags'), Var('asset')))), role: Role('functionrole_manipulate_fweets'), }) -
生成迁移 与
npx fauna-schema-migrate generate或通过由run生成将查看资源文件夹和迁移文件夹,并确定自我们上次运行生成以来资源文件夹中的变化 。 生成将在.fql文件中生成迁移的 FQL 。 该工具将核实资源中是否有所有参考资源。 例如,您目前无法创建一个可以保证收藏安全的角色,而该收藏不在您的资源文件夹中 .
为什么这个中间步骤? 这样做是有用的,因为迁移还可以包含JavaScript,它可能从其他文件中导入,以最大限度地再利用和FQL组成. 如果我们改变外部 JavaScript 文件, 我们可能会改变旧的迁移 。 将JS文件生成的FQL 变成一个纯粹独立的.fql文件, 更改外部导入的文件将不再影响迁移( 但是运行生成时, 如果结果的查询已经改变, 将触发新的迁移)
-
核实迁移情况
该工具仍在β中,并严重依赖FQL json格式的比较. 在一些先进的情景中进行了测试。 当先起用. 检查迁移文件夹中的迁移结果是否正确 。 迁移文件夹将包含不同的迁移文件夹, 名称为时间戳 。 每个生成的迁移包含每个创建/更新/删除的资源的.fql文件. 下面是一个例子结构:
fauna > migrations > 2021-01-25T20:49:16.074Z > create-collection-accounts.fql > create-collection-comments.fql > create-index-accounts-by-name.fql > 2021-02-09T15:49:58.115Z > create-collection-fweets.fql > create-index-all_fweets.fql不要手工编辑迁移,除非你永远不会使用 生成如果有人想用手书写移民,让我们知道,我们稍后可以为此再加一招。 迁移可以包含以下顶级声明.
CreateCollection(...) CreateIndex(...) CreateFunction(...) CreateRole(...) CreateAccessProvider(...) Update(...) Delete(...) -
随想应用或回滚.
一旦有迁移,就使用应用和回滚来应用或回滚数据库中的迁移.
npx fauna-schema-migrate applynpx fauna-schema-migrate rollback与帮助管理动物资源的现有工具不同,这些功能将通过使用Let语句将所有将要执行的资源迁移合并为一个交易。 要么全部交易失败,要么完成,任何交易都不会被部分应用. 迁移查询将打印为教育目的,如果打印量大,您可以选择通过-n或-no-打印删除.
两种应用的回滚都可以从交互式工具中运行,两种选择(互动工具中没有这种选择)。 第一个选择是申请/回滚的迁移量,第二个选择是支持儿童数据库,如进一步解释。 立即实施多重移徙将把这些多重移徙步骤结合起来 一个 智能交易。 这是一种优化,旨在加快在发展情景中从零开始建立数据库.
-
可选择 核实国家.
npx fauna-schema-migrate state
额外
ENV 变量 :
- FAUNA ADMIN KEY: 提供管理密钥
- FAUNA CHILD DB:为发展目的设置一个儿童数据库(见下一节)
- FAUNA LEGACY:删除可能不支持它的遗留终端的花式输出,或者如果您只是不喜欢它或者想要在没有框的情况下复制生成的FQL查询.
- FAUNA NOPRINT:不要打印FQL迁移.
- FAUNADB DOMAIN:与动物云以外的环境相接. 默认值为 “ db.fauna.com ” , 但也可能是您的本地嵌入器 IP 或预览组 .
- FAUNADB SCHEME:默认方案是“https”,主要用于本地开发,可以通过此环境变量设置为“http”
- FAUNAB Port:默认端口为443个,用于本地开发,并带有一个插头图像,您需要覆盖这个.
利用儿童数据库加快地方发展
其中一个参数,FAUNA CHILD DB在开发中是有用的,以防你经常发现自己完全对数据库进行微调并从头开始重新应用一切. 这样的话,你可能会碰到缓存,它要求你等待60秒后才能重新创造资源. FAUNA CHILD DB 将会在孩子数据库中创建您的资源,而不是在管理员指定的数据库中创建。 当使用 FAUNA CHILD DB 并在第一次交易前滚动(例如: npx fauna-schema-migrate rollback all)回滚将会对数据库投出核弹,而不是应用回滚,这基本上避免了60秒缓存.
管理多个数据库
通过添加文件夹支持儿童数据库 数字 在资源目录中。 这样可以定义儿童数据库中的资源(重复)。 一个潜在的结构可以是:
fauna > resources > ... resources for the root db ...
> dbs > nameOfchildDb1 > ... resources ...
> nameOfChildDb2 > ...
> dbs > nameOfChild1OfChildDb2 > ...
“ dbs” 名称可以在配置中配置 。 运行时 npx fauna-schema-migrate generate 该工具将产生移徙,以建立儿童数据库并产生儿童数据库内所有资源的移徙。 上述情况将导致在根数据库上进行迁移,以创建两个儿童数据库,并在迁移文件夹内设立一个dbs文件夹,其中将包括所有儿童数据库的迁移情况等。 儿童数据库的迁移与根数据库完全分开。 目前我们无法以交易方式更新多个数据库,一些生成步骤可能没有特定数据库的新迁移。 因此,对多个数据库实施应用命令可能毫无意义.
运行时 npx fauna-schema-migrate apply 或者说 npx fauna-schema-migrate rollback 根据参数,将只应用一个数据库的数据库迁移,默认是管理关键点的根数据库。 因此,运行 npx fauna-schema-migrate apply 没有参数,将运行根数据库的迁移.
运行 npx fauna-schema-migrate apply 1 nameOfChildDb1 将在第一个儿童数据库中应用迁移。 运行 npx fauna-schema-migrate apply 1 nameOfChildDb2 namdOfChild1OfChildDb2 将对第二个儿童数据库的儿童进行迁移。 这个功能是 没有( 是) 可在交互式版本中找到.
从今往后何处去?
可能的延长
-
图QL计划, 这很容易被添加。 复杂的部分是,如果资源文件夹中存在 GraphQL 计划,我们要么确保知道为避免冲突而创建的 GraphQL 计划资源,要么将 Creat 语句转换为 Creat OrUpdate 语句.
-
从现有数据库复制计划:用户通常从测试仪表板上的动物开始,将现有的数据库并下载计划作为继续发展的资源是有意义的。 目前这种情况已超出范围.
-
显示用作库的函数:为了集成测试的目的,也许应该能够按程序运行部分功能,而不必称之为命令行工具 https://github.com/fauna-labs/fauna-schema-migrate/blob/master/tests/ helpers.ts 互联网档案馆的存檔,存档日期2014-12-12 它本身就是一个很好的例子。 您可以很容易地提供一个资源文件夹, 并利用这些功能来建立针对动物的整合测试, 如下面的片段 .
sinon.stub(Config.prototype, 'getResourcesDir') .returns(Promise.resolve(path.join(dir, folder))) const planned = await planMigrations() const migrations = await generateMigrations(planned) const time = new Date().toISOString() await writeMigrations([], migrations, time) const res = await apply(1)它需要自定义资源文件夹(通过切换配置设置),并应用该文件夹中的任何内容进行此测试。 我想许多人会想与France UDFs/Roles建立测试, 他们可以从库中获利, 如果库中以简化格式(基因/应用/回滚/.)暴露这种功能.
-
计划步骤: 保存将应用于计划(类似于地平线)的FQL是完全合理的. 这样,我们就可以核实计划,并在当地实施计划,在生产中进行,但风险较小,可能有所不同.
-
仅迁移模式 : 您是否只使用. fql 文件, 并且不关心单独的资源文件夹来妥善组织资源, 那么您可能想要直接写入迁移 。 我们可以为此提供一种方法,以便在配置中加以界定.
-
无迁移模式 : 或者您更喜欢在不迁移的情况下使用这样的工具, 类似于地平线, 定义资源并仅更新云。 无论做什么 这也可能是我们在配置中提供的一种方法.
-
校正计划以对抗云:我们理论上可以验证迁移是否有效,这取决于云中存在什么,以避免在用户手动改变其数据库计划的最后可能时刻发现问题. 例如,当某个角色被更新时,我们可以发现它指的是被删除的集合。 目前交易会中止并丢出一个可能足够好的错误 。 可能仍有必要核实是否有人手动篡改了云图并看到差异和/或纠正差异.
请让我们知道你的要求 这样我们就能决定下一步要做什么了.
哲学
这些是有关该工具为什么是按原样设计的一些广泛的说明.
保持 FQL 可替换
与SQL,Cypher或ORM等其它查询语言相比,FranceDB查询语言(FQL)有很大不同. FQL中值得拥抱的特征之一是写出FQL查询本质上是函数构成. 例如:
Collection("accounts")
仅指收藏。 把它扔到另一个函数中, 以获得该集合中文档的引用 .
Ref(Collection('accounts'), '268431417906561542')
美丽的部分是,这些只是定义您查询的函数,我们可以使用主机语言(在此情况下是JavaScript)开始保存查询的片段以重新使用. 一个非常愚蠢的例子是:
const accountCollection = Collection("accounts")
const account = Ref(accountCollection,"268431417906561542")
...
但你可以想象当查询执行复杂的交易逻辑或开始大量加入时,这变得非常有用. 在许多例子中,比如 风味 或者说 认证骨架 以只定义一次返回格式,或者写入可以很容易地混入其他查询的可重复使用片段。 例如,在JavaScript中,可以将创建新用户但也执行速率限制并添加验证的查询抽象如下:
function CreateUser(email, password) {
let FQLStatement = <query to create a user>
FQLStatement = ValidateEmail(FQLStatement, email, ['data', 'email'])
FQLStatement = ValidatePassword(FQLStatement, password, ['data', 'password'])
return AddRateLimiting('register', FQLStatement, email)
}
校验邮件 校验Password 或 AddRateLimiting 所做的并不重要, 但重要的是,这种可相容性可以被使用, 我们希望它不会与我们的移民冲突。 如果我们直接使用许多移徙框架所广泛使用的方法,即编写铁路普遍使用的上下声明(据我所知)......。 例如:
module.exports.up = () => {
return CreateCollection({ name: 'Users' })
}
module.exports.down = () => {
return Delete(Collection('Users'))
}
如果上面的定义看起来像:
import { CreateOrUpdateFunction } from './../helpers/fql'
module.exports.up = () => {
CreateFunction(
'register',
Query(Lambda(['email', 'password'],
RegisterAccountWithEmailVerification(Var('email'), Var('password'))))
)
}
...
你的移民已经不在了 已固定 因为这个很重要的代码可以和迁移分开发展 这可能很难管理 这对于索引和集合的创建来说是不太可能的,但对于想要分享某种逻辑的用户定义函数来说,这成为了一个真正的问题.
减少工作,减少出错的可能性.
这个计划框架库的构思不仅是为了帮助支持稳定的计划迁移. 首先它旨在帮助将FranceDB资源表达为代码. 本质上支持相当于基础设施的资源作为代码(IaC),但你无法真正称之为"基础设施",因为FranceDB为您处理所有基础设施.
如果我们定义一个函数、索引或集合如下
module.exports.up = () => {
CreateFunction(name, body)
}
下行功能可以很容易地导出,所以要求用户写这个会有点傻. 特别是因为下行移民往往没有经过彻底的检验,所以很容易被误判.
相反,我们选择让用户定义 Create 语句,并在我们注意到自上次迁移以来资源已发生变化时,在滚动回或甚至从更新语句中自动获取下调语句.
检测依赖性.
功能可以依赖于角色,也可以依赖于收藏,通常你会在一个迁移中定义这些. 这需要你有时:
- 定义角色
- 定义使用该角色的函数
- 定义可以调用函数的角色.
而不是要求用户考虑这个命令,我们会发现它并命令不同的资源在 一次移徙 自动.
资源概况
在自己写动物的例子时,我喜欢我的资源被很好地呈现出来,以方便按类型或领域寻找资源. 上下迁移不能提供 分散你的资源 在一个无组织系列的文件。 在FQL或JS的文件中,拥有一个有简单名字的资源文件夹,没有时间戳,我可以如何组织我想要的东西,使寄存器更加清晰.
交换动物功能的格式 ?
如果这种方法得到我们社区的接受,我们可以有一个简单的统一格式,在储存库中分享计划文件。 我现在可以将一些动物寄存器装入一个GitHub寄存器,处理特定的功能. 譬如说,
- 认证骨架,用于设置基本或高级认证情景所需的函数,角色,索引,收藏,作为起点. 由用户执行前端/后端执行(当然,我们将继续提供附带的应用程序)
- 具有用户定义函数的存储器,以应用限制其所需的索引和收藏的其他函数的速率.
- 将用户包装在一个存储器中促进功能,例如: https://forums.fauna.com/t/logb-函数/1513/3。 。 。 .
关于数据迁移的说明
这个图书馆是 没有 用于数据迁移。 基本上,自Pagination开始, 当人们试图写出巨大的数据迁移, 这意味着一个巨大的数据迁移不能在一个交易中进行。 这种巨大的数据迁移很少指定回滚脚本. 相反,开发者通常在做之前先取一个备份,在现实生活中的数据上进行广泛的测试或者理想的测试. 避免完全需要大数据迁移。 如有必要,往往表明申请的移民策略应该被修改,因为一个持续了几个小时的庞大移民交易也是一个巨大的风险.
备选战略:
相反,您可以在您部署新代码时开始迁移,在迁移开始和完成批次后保留时间戳,核实哪些新数据仍然被插入到旧代码中,并且应当迁移并再次通过页面。 直到我们到达一个点,“新数据”是一个空页,在这种情况下,我们成功地迁移了所有数据.
这显然需要您的代码 能够处理旧格式 作为新的格式 数据在特定的时间跨度 这是可取的 不论数据库。 由于执行过程困难,涉及许多服务,有时根本无法做到这一点。 在这种情况下,你可以做两件事:
- 临时更改您的查询以使用 FranceDB 的时态和暂停/ 屏蔽新创建/ 写入( 读取、 块写) 来绘制快照
- 在迁移完成之前暂时取消申请 (屏蔽既读又写)
还需要吗?
也许需要将小种子数据输入到您的数据库中, 或者在研究一个单独的 npm 库来帮助这些复杂的数据迁移时可能会有价值 。 告诉我们你需要什么 你的反馈对我们很重要.
灵感
这个图书馆的灵感来自优秀的数据库图书馆和社区用户的努力,例如: