מיגרציות בסיסי נתונים הן שינויים המבוצעים על בסיס נתונים. שינויים אלה עשויים לכלול שינוי הסכימה של טבלה, עדכון הנתונים בקבוצת רשומות, הוספת נתונים או מחיקת טווח של רשומות.

מיגרציות בסיסי נתונים לרוב מתבצעות לפני שמיישמים את האפליקציה ואינן מתבצעות בהצלחה יותר מפעם אחת עבור אותו בסיס נתונים. כלים למיגרציות בסיסי נתונים שומרים היסטוריה של המיגרציות שבוצעו בבסיס נתונים כך שניתן לעקוב אחריהן למטרות עתידיות.

במאמר זה, תלמד כיצד להקים ולהריץ מיגרציות בסיסי נתונים באפליקציית API מינימלית ב-Node.js. אנחנו נשתמש ב-ts-migrate-mongoose ובסקריפט npm כדי ליצור מיגרציה ולהוסיף נתונים לבסיס נתונים MongoDB. ts-migrate-mongoose תומך בהרצת סקריפטי מיגרציה מקוד TypeScript כמו גם מקוד CommonJS.

ts-migrate-mongoose הוא מסגרת מיגרציה עבור פרויקטי Node.js המשתמשים ב-mongoose כממפה בין אובייקטים לנתונים. היא מספקת תבנית לכתיבת סקריפטי מיגרציה. היא גם מספקת הגדרה להרצת הסקריפטים באופן תכנותי ומן ה-CLI.

תוכן העניינים

כיצד להגדיר את הפרוייקט

כדי להשתמש ב-ts-migrate-mongoose להגדרת מסד נתונים, יש לך צורך בפרוייקט הבא:

  1. פרוייקט Node.js עם mongoose מותקן כתלות.

  2. מסד נתונים MongoDB מחובר לפרוייקט.

  3. MongoDB Compass (אופציונלי – כדי לאפשר לנו לראות את השינויים במסד הנתונים).

מאגר התחלה שניתן לשכפל מ-ts-migrate-mongoose-starter-repo נוצר לנוחות. שכפל את המאגר, מלא את משתני הסביבה והתחל את היישום על ידי הרצת הפקודה npm start.

בקר ב-http://localhost:8000 באמצעות דפדפן או לקוח API כמו Postman והשרת יחזיר טקסט "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 – ה-URI של מסד הנתונים Mongo. זהו אותו דבר כמו כתובת ה-URL של המסד נתונים.

  • MIGRATE_MONGO_COLLECTION – שם האוסף (או טבלה) שבו ישמרו ההעברות. ערך ברירת המחדל הוא migrations שזה מה שמשמש בפרויקט זה. ts-migrate-mongoose שומר העברות ב-MongoDB.

  • MIGRATE_MIGRATIONS_PATH – הנתיב לתיקייה לאחסון וקריאת סקריפטי העברות. ערך ברירת המחדל הוא ./migrations שזה מה שמשמש בפרויקט זה.

כיצד לזרוע נתוני משתמש עם ts-migrate-mongoose

הצלחנו ליצור פרויקט ולחבר אותו בהצלחה למסד נתונים של Mongo. בנקודה זו, אנו רוצים לזרוע נתוני משתמש לתוך מסד הנתונים. אנו צריכים:

  1. ליצור אוסף משתמשים (או טבלה)

  2. להשתמש ב-ts-migrate-mongoose כדי ליצור סקריפט העברה לזריעת נתונים

  3. להשתמש ב-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.

ניתן לעדכן את הקוד ב-./migrations/<timestamp>-seed-users.ts לקוד בחתיכה הבאה:

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 אפשר להריץ את הפונקציה up של כל הסקריפטים בתיקיית ./migrations שיש להן state של down במסד הנתונים.

כדי להפעיל את ההעברה לפני שהיישום מתחיל, אנו משתמשים בנסיונות npm. נסיונות npm עם קידומת של pre ירוצו לפני נסיון בלעדי הקידומת pre. לדוגמה, אם יש נסיון dev ונסיון predev, כל פעם שהנסיון dev יופעל עם npm run dev, הנסיון predev יופעל אוטומטית לפני שהנסיון dev יופעל.

נשתמש בתכונה זו של נסיונות npm כדי לשים את פקודת ts-migrate-mongoose בנסיון prestart כדי שההעברה תרוץ לפני שהנסיון start ייפעל.

עדכן את קובץ package.json כך שיהיה לו נסיון prestart שיריץ את פקודת ts-migrate-mongoose להרצת פונקציית ה-up של נסיונות ההעברה בפרויקט.

  "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"
    }
  ]
}

שימו לב שאם האפליקציה תרוץ שוב, הסקריפט של ההגירה לא ירוץ יותר כי הstate של ההגירה יהיה עכשיו up לאחר שהיא רצה בהצלחה.

בדקו את הסניף fetch-users של המאגר כדי לראות את המצב הנוכחי של בסיס הקוד בנקודה זו במאמר.

סיכום

הגירות שימושיות כאשר בונים אפליקציות ויש צורך להנחיל נתונים ראשוניים לבדיקה, להנחיל משתמשים מנהלתיים, לעדכן את הסכימה של מסד הנתונים על ידי הוספת או הסרת עמודות ועדכון הערכים של עמודות ברבים רשומות בבת אחת.

ts-migrate-mongoose יכול לעזור לספק מסגרת להרצת הגירות עבור האפליקציות שלך ב-Node.js אם אתה משתמש ב-Mongoose עם MongoDB.