資料庫遷移是對資料庫所做的修改。這些修改可能包括更改表格的結構、更新一組記錄中的數據、填充數據或刪除一系列記錄。
資料庫遷移通常在應用程序啟動前運行,且對於同一資料庫不會成功運行多於一次。資料庫遷移工具保存了在資料庫中運行的遷移歷史,以便將來跟踪。
在本文中,您將學習如何在一個最小的 Node.js API 應用程序中設置和運行資料庫遷移。我們將使用 ts-migrate-mongoose 及 npm 腳本來創建遷移並將數據填充到 MongoDB 資料庫中。ts-migrate-mongoose 支援從 TypeScript 代碼以及 CommonJS 代碼運行遷移腳本。
ts-migrate-mongoose 是一個針對使用 mongoose 作為物件資料映射器的 Node.js 專案的遷移框架。它提供了編寫遷移腳本的模板,並提供了從 CLI 和以程式方式運行腳本的配置。
目錄
如何設置專案
要使用ts-migrate-mongoose進行數據庫遷移,您需要擁有以下內容:
-
安裝mongoose作為依賴項的Node.js專案。
-
連接到專案的MongoDB數據庫。
-
MongoDB Compass(可选 – 以便我们查看数据库中的更改)。
已创建一个可从ts-migrate-mongoose-starter-repo克隆的入门存储库以便使用。克隆存储库,填写环境变量,并通过运行npm start
命令启动应用程序。
访问http://localhost:8000,使用浏览器或像Postman这样的API客户端,服务器将返回“Hello there!”文本,以显示入门应用程序按预期运行。
如何为项目配置ts-migrate-mongoose
要为项目配置ts-migrate-mongoose,请使用此命令安装ts-migrate-mongoose:
npm install ts-migrate-mongoose
ts-migrate-mongoose允许使用JSON文件、TypeScript文件、.env
文件或通过CLI进行配置。建议使用.env
文件,因为配置内容可能包含数据库密码,不应将其暴露给公众。 .env
文件通常通过.gitignore
文件隐藏,因此更安全。该项目将使用.env
文件进行ts-migrate-mongoose配置。
文件应包含以下键及其值:
-
MIGRATE_MONGO_URI
– Mongo数据库的URI。与数据库URL相同。 -
MIGRATE_MONGO_COLLECTION
– 用於存儲遷移的集合(或表)的名稱。默認值為migrations,這是該項目中使用的值。ts-migrate-mongoose將遷移保存到MongoDB。 -
MIGRATE_MIGRATIONS_PATH
– 用於存儲和讀取遷移腳本的文件夾路徑。默認值為./migrations
,這是該項目中使用的值。
如何使用ts-migrate-mongoose種子用戶數據
我們已經成功創建了一個項目並將其成功連接到Mongo數據庫。此時,我們希望將用戶數據種植到數據庫中。我們需要:
-
創建用戶集合(或表)
-
使用ts-migrate-mongoose創建一個遷移腳本來種植數據
-
使用ts-migrate-mongoose運行遷移以在應用程序啟動之前將用戶數據種植到數據庫中
1. 使用 Mongoose 創建一個用戶集合
Mongoose 模式可用於創建用戶集合(或表)。用戶文檔(或記錄)將擁有以下字段(或列):email
、favouriteEmoji
和 yearOfBirth
。
要為用戶集合創建 Mongoose 模式,請在項目根目錄中創建一個 user.model.js
文件,並包含以下代碼片段:
const mongoose = require("mongoose");
const userSchema = new mongoose.Schema(
{
email: {
type: String,
lowercase: true,
required: true,
},
favouriteEmoji: {
type: String,
required: true,
},
yearOfBirth: {
type: Number,
required: true,
},
},
{
timestamps: true,
}
);
module.exports.UserModel = mongoose.model("User", userSchema);
2. 使用 ts-migrate-mongoose 創建遷移腳本
ts-migrate-mongoose 提供可用於創建遷移腳本的 CLI 命令。
在項目根文件夾中運行 npx migrate create <name-of-script>
將在 MIGRATE_MIGRATIONS_PATH
文件夾中創建一個腳本(在我們的案例中為 ./migrations
)。<name-of-script>
是我們希望創建遷移腳本文件時的名稱。
要創建一個遷移腳本以填充用戶數據,請運行:
npx migrate create seed-users
該命令將在 ./migrations
文件夾中創建一個文件,名稱格式為 <timestamp>-seed-users.ts
。該文件將包含以下代碼片段內容:
// 在此處導入您的模型
export async function up (): Promise<void> {
// 在此處編寫遷移
}
export async function down (): Promise<void> {
// 在此處編寫遷移
}
up
函數用於運行遷移。如果需要,down
函數用於撤消 up
函數的執行。在我們的情況下,我們正在嘗試將用戶種子數據添加到數據庫中。 up
函數將包含將用戶種子數據添加到數據庫中的代碼,而 down
函數將包含刪除在 up
函數中創建的用戶的代碼。
如果使用 MongoDB Compass 檢查數據庫,遷移集合將具有以下類似的文檔:
{
"_id": ObjectId("6744740465519c3bd9c1a7d1"),
"name": "seed-users",
"state": "down",
"createdAt": 2024-11-25T12:56:36.316+00:00,
"updatedAt": 2024-11-25T12:56:36.316+00:00,
"__v": 0
}
遷移文檔的 state
字段設置為 down
。成功運行後,它會更改為 up
。
您可以將代碼更新為下面片段中的代碼:
require("dotenv").config() // 加載環境變量
const db = require("../db.js")
const { UserModel } = require("../user.model.js");
const seedUsers = [
{ email: "[email protected]", favouriteEmoji: "🏃", yearOfBirth: 1997 },
{ email: "[email protected]", favouriteEmoji: "🍏", yearOfBirth: 1998 },
];
export async function up (): Promise<void> {
await db.connect(process.env.MONGO_URI)
await UserModel.create(seedUsers);}
export async function down (): Promise<void> {
await db.connect(process.env.MONGO_URI)
await UserModel.delete({
email: {
$in: seedUsers.map((u) => u.email),
},
});
}
3. 在應用啟動之前運行遷移
ts-migrate-mongoose 為我們提供了 CLI 命令,用於運行遷移腳本的 up
和 down
函數。
使用 npx migrate up <name-of-script>
可以運行特定腳本的 up
函數。使用 npx migrate up
可以運行數據庫中 state
為 down
的 ./migrations
文件夾中所有腳本的 up
函數。
在應用程序啟動之前運行遷移,我們會使用 npm 腳本。具有前綴pre
的 npm 腳本將在沒有pre
前綴的腳本之前運行。例如,如果有一個dev
腳本和一個predev
腳本,每當運行dev
腳本時使用npm run dev
,predev
腳本將在運行dev
腳本之前自動運行。
我們將使用 npm 腳本的這個功能將 ts-migrate-mongoose 命令放在一個prestart
腳本中,以便在start
腳本運行之前運行遷移。
更新package.json
文件,添加一個運行 ts-migrate-mongoose 命令以運行項目中遷移腳本的up
功能的prestart
腳本。
"scripts": {
"prestart": "npx migrate up",
"start": "node index.js"
},
有了這個設置,當執行npm run start
來啟動應用程序時,prestart
腳本將運行以使用 ts-migrate-mongoose 執行遷移並在應用程序啟動之前對數據庫進行種子化。
執行npm run start
後,您應該會看到以下類似的片段:
Synchronizing database with file system migrations...
MongoDB connection successful
up: 1732543529744-seed-users.ts
All migrations finished successfully
> [email protected] start
> node index.js
MongoDB connection successful
Server listening on port 8000
查看存儲庫的seed-users分支,以查看文章中此時代碼庫的當前狀態。
如何構建用於獲取種子數據的 API 端點
我們可以構建一個 API 端點來獲取數據庫中種子用戶數據。在server.js
文件中,將代碼更新為下面片段中的代碼:
const { UserModel } = require("./user.model.js")
module.exports = async function (req, res) {
const users = await UserModel.find({}) //從數據庫中獲取所有用戶
res.writeHead(200, { "Content-Type": "application/json" });
return res.end(JSON.stringify({ //返回獲取的用戶數據的JSON表示
users: users.map((u) => ({
email: u.email,
favouriteEmoji: u.favouriteEmoji,
yearOfBirth: u.yearOfBirth,
createdAt: u.createdAt
}))
}, null, 2));
};
如果我們啟動應用程序並訪問http://localhost:8000使用Postman或瀏覽器,我們會得到一個類似下面的JSON響應:
{
"users": [
{
"email": "[email protected]",
"favouriteEmoji": "🏃",
"yearOfBirth": 1997,
"createdAt": "2024-11-25T14:18:55.416Z"
},
{
"email": "[email protected]",
"favouriteEmoji": "🍏",
"yearOfBirth": 1998,
"createdAt": "2024-11-25T14:18:55.416Z"
}
]
}
請注意,如果再次運行應用程序,遷移腳本將不再運行,因為遷移的狀態
在成功運行後將為上
。
請查看存儲庫的fetch-users分支,以查看本文中代碼庫的當前狀態。
結論
在構建應用程序時,當需要為測試種子初始數據、種子管理用戶、通過添加或刪除列來更新數據庫模式以及更新多條記錄的列值時,遷移是很有用的。
如果您使用Mongoose和MongoDB,ts-migrate-mongoose可以幫助為您的Node.js應用程序運行遷移提供框架。
Source:
https://www.freecodecamp.org/news/handle-mongodb-migrations-with-ts-migrate-mongoose/