- Published on
เรียนรู้การใช้งาน migrate-mongo
สวัสดีคุณผู้อ่านทุกท่านจร้า วันนี้เจมส์จะมาเขียนบทความเกี่ยวกับการใช้งาน migrate-mongo ครับ เราจะใช้ตอนที่ต้องการ migrate database คือมีข้อมูลเก่าอยู่แล้ว และอยากเพิ่ม หรือแก้ไข field ใน collection นั้นๆ หรือเพิ่ม collection ใหม่ขึ้นมาโดยดูข้อมูลจากอีก collection นึง เป็นต้น
อธิบายอาจจะไม่ค่อยเห็นภาพเท่าไร เรามาลองทำกันเลยดีกว่าครับจะได้เห็นภาพมากขึ้น
มาเริ่มกันเลย
ติดตั้ง migrate-mongo
เปิด Terminal และพิมพ์คำสั่ง
npm install -g migrate-mongo
หลังจากติดตั้งเรียบร้อย ให้เราลองใช้คำสั่ง
migrate-mongo --version
ถ้าหากไม่มีอะไรผิดพลาด จะแสดง version ที่เราติดตั้งขึ้นมา
Clone Project ตัวอย่าง
ในขั้นตอนนี้สำหรับคนที่ต้องการทำตามเน้อครับ เจมส์เตรียมโปรเจคที่มี MongoDB ไว้ให้เรียบร้อยแล้ว โดยเราจะ Clone Project นี้ลงมาแล้วก็สั่งให้คำสั่งให้ restore ข้อมูลใส่ใน MongoDB เตรียมไว้ก่อน
สามารถเข้าไป clone ได้ที่นี่เลยครับ example-mongo-restore หรือจะใช้คำสั่ง
git clone git@github.com:jame3032002/example-mongo-restore.git
จากนั้นให้ เข้าไปใน project โดยใช้คำสั่ง
cd example-mongo-restore
จากนั้นให้ใช้คำสั่ง
docker-compose up
เมื่อ run เรียบร้อยแล้ว ให้เปิดอีก Terminal ขึ้นมาครับ เข้ามาที่ root project เดิมที่เรา clone ลงมา จากนั้นให้ใช้คำสั่ง
sh restore.sh
ในที่นี้เจมส์เขียน script ไว้ใน คำสั่ง restore.sh
ไว้แล้ว โดยคำสั่งที่เขียนไว้คือให้ restore ข้อมูลใส่ใน db ที่เราสร้าง
เราสามารถลองใช้ robo 3T
connect เข้าไปดูว่ามีข้อมูลอะไรบ้าง ซึ่งหากคุณผู้อ่าน clone แล้วทำตามคำอธิบายข้างต้นโดยไม่ได้เปลี่ยนค่าอะไร
- username ที่ใช้ connect MongoDB คือ kajame
- password ที่ใช้ connect MongoDB คือ 111111
- database ที่ใช้ connect MongoDB คือ example
ดูในจากไฟล์ docker-compose.yaml ในโปรเจคที่เจมส์เตรียมไว้ให้
ในตอนนี้เรามีข้อมูลเรียบร้อยแล้ว เราจะมาลอง migrate ข้อมูลเพิ่มเข้าไปกันครับ โดยเจมส์จะขออ้างอิงจากข้อมูลในตัวอย่างของเจมส์นะครับ
มาลอง Migrate ข้อมูลกัน
ขั้นแรกให้เราเข้าไปใน project ของเรา ในที่นี่เดี๋ยวเจมส์จะเข้าไปใน project ที่ใช้เป็นตัวอย่างข้างต้นนะครับ จากนั้นให้เราสร้าง directory ชื่อที่เราต้องการให้เก็บข้อมูลใส่ไว้ในนั้น ในที่นี้เจมส์จะสร้างว่า database-migrations
และเข้าไปใน directory ที่สร้าง
mkdir database-migrations
cd database-migrations
จากนั้นให้ใช้คำสั่ง
migrate-mongo init
หลังจากที่ใช้คำสั่ง migrate-mongo init
จะพบว่ามีไฟล์ migrate-mongo-config.js
และ directory ชื่อ migrations
ถูกสร้างขึ้นมา
ในไฟล์ migrate-mongo-config.js
จะเป็นการตั้งค่าต่าง ๆ ซึ่งในตอนนี้เราจะสนใจแค่ในส่วน url ก่อนครับ
- ตั้งค่า url โดยเราจะเปลี่ยนเป็น
mongodb://kajame:111111@localhost:27017/example
ซึ่งในส่วนของการตั้งค่าของ migrate-mongo-config.js ให้เหลือแค่นี้ได้เลยครับ
// In this file you can configure migrate-mongo
const config = {
mongodb: {
url: "mongodb://kajame:111111@localhost:27017/example",
},
// The migrations dir, can be an relative or absolute path. Only edit this when really necessary.
migrationsDir: "migrations",
// The mongodb collection where the applied changes are stored. Only edit this when really necessary.
changelogCollectionName: "changelog",
// The file extension to create migrations and search for in migration dir
migrationFileExtension: ".js",
// Enable the algorithm to create a checksum of the file contents and use that in the comparison to determine
// if the file should be run. Requires that scripts are coded to be run multiple times.
useFileHash: false,
// Don't change this, unless you know what you're doing
moduleSystem: "commonjs",
};
module.exports = config;
จากนั้นเราจะมาสร้าง migration script กันครับ
สร้างไฟล์ migration script
ให้เราเปิด Terminal และเข้าไปใน directory database-migrations ที่เราสร้างก่อนหน้านี้ จากนั้นให้ใช้คำสั่ง
migrate-mongo create add_user_collection_from_tweet_collection
ซึ่งมีรูปแบบคือ
migrate-mongo create [คำอธิบาย]
เมื่อใช้คำสั่งสร้าง migration script แล้วจะพบว่ามีไฟล์หนึ่งไฟล์ถูกสร้างมาใน directory migrations
ไฟล์ของเจมส์ที่ถูกสร้างมาชื่อ 20231126111354-add_user_collection_from_tweet_collection.js
ของคุณผู้อ่านชื่อไฟล์ที่ได้อาจจะแตกต่างกันกับเจมส์นะครับ ไม่ต้องตกใจ
ซึ่งส่วนนี้คือส่วนที่เราจะมาเขียน script สำหรับ migrate mongo กันครับ
method ชื่อ up เราจะเขียน script ที่สำหรับใช้ migrate
method ชื่อ down เราจะเขียน script ที่ใช้สำหรับ rollback กลับ (กรณีที่เพิ่มไปแล้ว แล้วเกิดปัญหา)
ตัวอย่างโจทย์ที่ได้รับมาคือ บริษัทต้องการเพิ่ม collection users
โดยดูจาก user.id
ใน collection tweets
ซึ่งต้องการแค่ field id
, name
ใน collection user เท่านั้น
เราจะสามารถเขียนไฟล์เพื่อ migrate ได้ดังนี้ครับ
module.exports = {
async up(db, client) {
console.log("=== start add user from tweets collection ===");
const tweets = await db.collection("tweets").find({}).toArray();
for (const [index, tweet] of tweets.entries()) {
const { user } = tweet;
const u = await db.collection("users").findOne({ id: user.id });
if (!u) {
await db.collection("users").insertOne({ id: user.id, name: user.name });
}
console.log(`Migrate Completed ${index}/${tweets.length}`);
}
console.log("=== end add user from tweets collection ===");
},
async down(db, client) {
db.collection("users").deleteMany({});
},
};
จากโค้ดในส่วน up คือเราจะให้มันดึงข้อมูลจาก collection tweets จากนั้น เอาผลลัพธ์ที่ได้โดยเอาข้อมูล user.id ที่ได้ มาหาใน collection users ถ้าหากว่าไม่มีข้อมูลใน collection user ก็เพิ่มข้อมูล user คนนั้นเข้าไป
จากโค้ดในส่วน down คือ เราจะลบ collection users ออกไป
จากนั้นให้ใช้คำสั่ง
migrate-mongo up
เมื่อเราเข้าไปดูใน robo3T
จะพบว่ามี collection ชื่อ changelog
เพิ่มขึ้นมา ส่วนนี้จะเป็น log เก็บไว้ว่าเรา migrate อันไหนไปแล้วบ้าง
และจะพบว่ามี collection ชื่อ users
ขึ้นมา ซึ่ง collection users
ที่เพิ่มขึ้นมานั้นก็มาจาก script ที่เราเขียนไว้ในก่อนหน้านี้นี่เองครับ
หากคุณผู้อ่านพบว่า เราอาจจะ migrate ผิด สามารถใช้คำสั่ง
migrate-mongo down
เพื่อ rollback ได้ แต่! คำสั่งใน method down ที่เราเขียนต้องถูกต้องด้วยนะครับ ไม่งั้นก็ยิ่งเละไปใหญ่ ^^
ถ้าใช้
migrate-mongo down
มันคือการ rollback กลับไป step ก่อนหน้าเท่านั้นนะครับ
หวังว่าบทความนี้จะมีประโยชน์กับคุณผู้อ่านทุกท่านเน้อครับ หากมีส่วนไหนผิดพลาดประการใด ก็ขออภัยมา ณ ที่นี้ด้วยเน้อครับ หรือหากคุณผู้อ่านมีส่วนไหนต้องการแนะนำเพิ่มเติม ก็สามารถพิมพ์ไว้ใน comment ได้เลยเน้อครับ