Saya hampir memiliki proyek saya siap diluncurkan. Saya punya rencana besar setelah peluncuran dan struktur database akan berubah - kolom baru di tabel yang ada serta tabel baru, dan asosiasi baru ke model yang ada dan model baru.
Saya belum menyentuh migrasi di Sequelize, karena saya hanya memiliki data pengujian yang tidak keberatan saya hapus setiap kali database berubah.
Untuk itu, saat ini saya menjalankan sync force: true
aplikasi saya saat dijalankan, jika saya telah mengubah definisi model. Ini menghapus semua tabel dan membuatnya dari awal. Saya dapat menghilangkan force
opsi untuk membuatnya hanya membuat tabel baru. Tetapi jika sudah ada yang berubah hal ini tidak berguna.
Jadi, begitu saya menambahkan migrasi, bagaimana cara kerjanya? Jelas saya tidak ingin tabel yang ada (dengan data di dalamnya) dihapus, jadi sync force: true
itu tidak mungkin. Pada aplikasi lain yang saya bantu kembangkan (Laravel dan kerangka kerja lainnya) sebagai bagian dari prosedur penerapan aplikasi, kami menjalankan perintah migrasi untuk menjalankan migrasi yang tertunda. Namun dalam aplikasi ini, migrasi pertama memiliki basis data kerangka, dengan basis data dalam keadaan di mana pada beberapa waktu awal pengembangan - rilis alfa pertama atau apa pun. Jadi, bahkan instance aplikasi yang terlambat ke pesta bisa mendapatkan kecepatan sekaligus, dengan menjalankan semua migrasi secara berurutan.
Bagaimana cara menghasilkan "migrasi pertama" seperti itu di Sequelize? Jika saya tidak memilikinya, instance baru dari aplikasi entah bagaimana nantinya tidak akan memiliki database kerangka untuk menjalankan migrasi, atau akan menjalankan sinkronisasi di awal dan akan membuat database dalam status baru dengan semua tabel baru dll, tetapi kemudian ketika mencoba untuk menjalankan migrasi mereka tidak masuk akal, karena mereka ditulis dengan database asli dan setiap iterasi berturut-turut dalam pikiran.
Proses pemikiran saya: pada setiap tahap, database awal ditambah setiap migrasi secara berurutan harus sama (plus atau minus data) database yang dihasilkan ketika sync force: true
dijalankan. Ini karena deskripsi model dalam kode menggambarkan struktur database. Jadi mungkin jika tidak ada tabel migrasi kita hanya menjalankan sinkronisasi dan menandai semua migrasi sebagai selesai, meskipun mereka tidak berjalan. Apakah ini yang perlu saya lakukan (bagaimana?), Atau Sequelize seharusnya melakukan ini sendiri, atau apakah saya menggonggong pohon yang salah? Dan jika saya berada di area yang tepat, tentunya seharusnya ada cara yang bagus untuk menghasilkan sebagian besar migrasi secara otomatis, mengingat model lama (dengan melakukan hash? Atau bahkan setiap migrasi dapat dikaitkan dengan komit? Saya akui, saya sedang berpikir dalam dunia git-sentris non-portabel) dan model baru. Ini dapat membedakan struktur dan menghasilkan perintah yang diperlukan untuk mengubah database dari lama ke baru, dan kembali, dan kemudian pengembang dapat masuk dan membuat perubahan yang diperlukan (menghapus / mentransisikan data tertentu dll).
Ketika saya menjalankan sekuel biner dengan --init
perintah itu memberi saya direktori migrasi kosong. Ketika saya kemudian menjalankannya, sequelize --migrate
itu membuat saya menjadi tabel SequelizeMeta tanpa apa pun di dalamnya, tidak ada tabel lain. Jelas tidak, karena biner itu tidak tahu cara mem-bootstrap aplikasi saya dan memuat model.
Saya pasti melewatkan sesuatu.
TLDR: bagaimana cara menyiapkan aplikasi saya dan migrasinya sehingga berbagai contoh aplikasi langsung dapat diperbarui, serta aplikasi baru tanpa database awal yang lama?
sync
untuk saat ini, idenya adalah bahwa migrasi "menghasilkan" seluruh database, jadi mengandalkan kerangka itu sendiri merupakan masalah. Alur kerja Ruby on Rails, misalnya, menggunakan Migrasi untuk semuanya, dan ini cukup mengagumkan setelah Anda terbiasa. Sunting: Dan ya, saya perhatikan pertanyaan ini cukup lama, tetapi karena belum pernah ada jawaban yang memuaskan dan orang-orang mungkin datang ke sini untuk mencari panduan, saya pikir saya harus berkontribusi.Jawaban:
Menghasilkan "migrasi pertama"
Dalam kasus Anda, cara paling andal adalah melakukannya hampir secara manual. Saya akan menyarankan untuk menggunakan alat sequelize-cli . Sintaksnya agak sederhana:
sequelize init ... sequelize model:create --name User --attributes first_name:string,last_name:string,bio:text
Ini akan membuat model DAN migrasi. Kemudian, gabungkan model yang ada secara manual dengan generated with sequelize-cli, dan lakukan hal yang sama dengan migrasi. Setelah melakukan ini, hapus database (jika memungkinkan), dan jalankan
Ini akan membuat skema akan migrasi. Anda harus melakukan ini hanya sekali untuk beralih ke proses pengembangan skema yang tepat (tanpa sinkronisasi: kekuatan, tetapi dengan migrasi otoritatif).
Nanti, saat Anda perlu mengubah skema:
sequelize migration:create
sequelize db:migrate
Menjalankan migrasi pada produksi
Jelas Anda tidak dapat melakukan ssh ke server produksi dan menjalankan migrasi dengan tangan. Gunakan umzug , alat migrasi kerangka kerja agnostik untuk Node.JS untuk melakukan migrasi tertunda sebelum aplikasi dimulai.
Anda bisa mendapatkan daftar migrasi yang tertunda / belum dijalankan seperti ini:
umzug.pending().then(function (migrations) { // "migrations" will be an Array with the names of // pending migrations. });
Kemudian jalankan migrasi ( di dalam callback ). Metode eksekusi adalah fungsi tujuan umum yang dijalankan untuk setiap migrasi yang ditentukan fungsi masing-masing:
umzug.execute({ migrations: ['some-id', 'some-other-id'], method: 'up' }).then(function (migrations) { // "migrations" will be an Array of all executed/reverted migrations. });
Dan saran saya adalah melakukannya sebelum aplikasi dimulai dan mencoba melayani rute setiap saat. Sesuatu seperti ini:
umzug.pending().then(function(migrations) { // "migrations" will be an Array with the names of // pending migrations. umzug.execute({ migrations: migrations, method: 'up' }).then(function(migrations) { // "migrations" will be an Array of all executed/reverted migrations. // start the server app.listen(3000); // do your stuff }); });
Saya tidak dapat mencoba ini sekarang, tetapi pada pandangan pertama seharusnya berhasil.
UPD April 2016
Setelah setahun, masih bermanfaat, sekian tips saya saat ini. Untuk saat ini, saya menginstal
sequelize-cli
paket sebagai ketergantungan langsung yang diperlukan , dan kemudian memodifikasi skrip startup NPMpackage.json
seperti ini:... "scripts": { "dev": "grunt && sequelize db:migrate && sequelize db:seed:all && node bin/www", "start": "sequelize db:migrate && sequelize db:seed:all && node bin/www" }, ...
Satu-satunya hal yang perlu saya lakukan di server produksi adalah
npm start
. Perintah ini akan menjalankan semua migrasi, menerapkan semua seeder dan memulai server aplikasi. Tidak perlu memanggil umzug secara manual.sumber
pending
dan kemudianexecute
melakukannyaumzug.up().then(function (migrations) { app.listen(3000); })
. Menurut dokumentasi umzug, ini akan menjalankan semua migrasi yang tertunda.Baru saja mempelajarinya sendiri, tapi saya rasa saya akan merekomendasikan menggunakan migrasi sekarang agar Anda terbiasa dengannya. Saya telah menemukan hal terbaik untuk mencari tahu apa yang terjadi dalam migrasi adalah dengan melihat sql pada tabel yang dibuat oleh
sequelize.sync()
dan kemudian membangun migrasi dari sana.Akan membuat file migrasi template di direktori migrasi. Anda kemudian dapat mengisinya dengan bidang yang perlu Anda buat. File ini perlu menyertakan
createdAt
/updatedAt
, bidang yang diperlukan untuk asosiasi, dll.Untuk pembuatan tabel awal ke bawah harus memiliki:
migration.dropTable('MyTable');
Tetapi pembaruan berikutnya pada struktur tabel dapat mengabaikan ini dan hanya menggunakan tabel alter.
Contoh pembuatan akan terlihat seperti:
module.exports = { up: function(migration, DataTypes, done) { migration.createTable( 'MyTable', { id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, bigString: {type: DataTypes.TEXT, allowNull: false}, MyOtherTableId: DataTypes.INTEGER, createdAt: { type: DataTypes.DATE }, updatedAt: { type: DataTypes.DATE } }); done(); }, down: function(migration, DataTypes, done) { migration.dropTable('MyTable'); done(); }
Untuk mengulang dari awal:
Saya menggunakan kopi untuk menjalankan file benih untuk mengisi tabel setelah:
Ini hanya memiliki fungsi buat di dalamnya yang terlihat seperti:
user = db.User.create username: 'bob' password: 'suruncle' email: '[email protected]' .success (user) -> console.log 'added user' user_id = user.id myTable = [ field1: 'womp' field2: 'rat' subModel: [ field1: 'womp' , field1: 'rat' ] ]
Ingatlah untuk
sync()
mengeluarkan indeks Anda dalam model Anda atau itu akan menimpa apa yang dilakukan migrasi dan seed.Docs ada di http://sequelize.readthedocs.org/en/latest/docs/migrations/ tentunya. Tetapi jawaban dasarnya adalah Anda harus menambahkan semua yang ada dalam diri Anda untuk menentukan bidang yang Anda butuhkan. Itu tidak melakukannya untuk Anda.
sumber
sequelize.sync()
memiliki skrip yang dihasilkan yang membuat semua tabel dan indeks dasar sebagai migrasi pertama Anda (mirip dengan rails 'schema.rb
.) Setelah membaca ini, tampaknya taruhan terbaik Anda adalah mengekspor skema awal Anda sebagai sql, lalu masukkan ke dalamexec
pernyataan besar di migrasi pertama Anda. Kemudian dari sana Anda menjalankan perubahan tambahan terhadap titik awal "versi 1.0" yang diketahui.Untuk pengembangan , sekarang ada opsi untuk menyinkronkan tabel saat ini dengan mengubah strukturnya. Menggunakan versi terbaru dari repo github sekuel , Anda sekarang dapat menjalankan sinkronisasi dengan
alter
parameter.Table.sync({alter: true})
Peringatan dari dokumen:
sumber
Sekarang dengan migrasi sekuel baru sangat sederhana.
Ini adalah contoh yang bisa Anda lakukan.
'use strict'; var Promise = require('bluebird'), fs = require('fs'); module.exports = { up: function (queryInterface, Sequelize) { return Promise .resolve() .then(function() { return fs.readFileSync(__dirname + '/../initial-db.sql', 'utf-8'); }) .then(function (initialSchema) { return queryInterface.sequelize.query(initialSchema); }) }, down: function (queryInterface, Sequelize) { return Promise .resolve() .then(function() { return fs.readFileSync(__dirname + '/../drop-initial-db.sql', 'utf-8'); }) .then(function (dropSql) { return queryInterface.sequelize.query(dropSql); }); } };
Ingat Anda harus mengatur:
"dialectOptions": { "multipleStatements": true }
pada konfigurasi database.
sumber
Saya membaca posting ini dan pertanyaan serupa, itu tidak benar-benar menjawabnya untuk saya. Migrasi berguna untuk menjalankan database lokal dan untuk memperbarui data dalam produksi
Saya mengajukan pertanyaan di sini dan menjawabnya juga: Alur kerja untuk menangani migrasi dan inisialisasi sekuel?
Versi TL-DR untuk proyek greenfield
.sql
file ke atassequelize init:migrate
di folder mana pun tempat Andamodels
beradasequelize migration:generate --name [name_of_your_migration]
("use strict"); /** * DROP SCHEMA public CASCADE; CREATE SCHEMA public * ^ there's a schema file with all the tables in there. it drops all of that, recreates */ const fs = require("fs"); const initialSqlScript = fs.readFileSync("./migrations/sql/Production001.sql", { encoding: "utf-8", }); const db = require("../models"); module.exports = { up: () => db.sequelize.query(initialSqlScript), down: () => db.sequelize.query(`DROP SCHEMA public CASCADE; CREATE SCHEMA public; `), };
dengan struktur folder umum ini
sequelize migration:generate --name [name_of_your_migration]
up
dandown
. Ini adalah pernyataan ALTER Anda untuk mengubah nama kolom, HAPUS, TAMBAHKAN kolom, dllsequelize db:migrate
npm install sequelize-auto
.sequelize-auto -o "./models" -d sequelize_auto_test -h localhost -u my_username -p 5432 -x my_password -e postgres
ditemukan di https://github.com/sequelize/sequelize-autoAnda dapat menggunakan git untuk melihat difflogs pada model Anda, seharusnya hanya ada perubahan yang mencerminkan perubahan dalam model database. Sebagai catatan tambahan, jangan pernah memodifikasi
models
langsung jika Anda menggunakansequelize auto
, karena ini akan membuatnya untuk Anda. Selain itu, Anda tidak lagi harus mengubah skema database Anda secara langsung dengan file SQL, asalkan ini adalah opsi karena Anda juga dapat mengimpor.sql
file tersebut.Sekarang skema database Anda sudah diperbarui, dan Anda secara resmi pindah ke sekuel migrasi database saja.
Semuanya dikontrol versi. Ini adalah alur kerja yang ideal untuk pengembang database dan backend
sumber
Gunakan versi. Versi aplikasi tergantung pada versi database. Jika versi baru memerlukan pembaruan database, buat migrasi untuk itu.
update: Saya memutuskan untuk meninggalkan migrasi ( KISS ) dan menjalankan skrip update_db (sync forse: false) bila diperlukan.
sumber
sync()
sama sekali, dan bahwa saya perlu menulis migrasi secara manual dari skema model versi lama ke model versi yang lebih baru?Agak terlambat, dan setelah membaca dokumentasi, Anda tidak perlu melakukan migrasi pertama yang Anda bicarakan. Yang harus Anda lakukan adalah memanggil
sync
untuk membuat tabel.sequelize.sync()
Anda juga dapat menjalankan sinkronisasi model sederhana dengan melakukan sesuatu seperti:
Project.sync()
tetapi saya pikir itusequelize.sync()
adalah kasus umum yang lebih berguna untuk proyek Anda (selama Anda mengimpor model yang baik pada waktu mulai).(diambil dari http://sequelizejs.com/docs/latest/models#database-synchronization )
Ini akan membuat semua struktur awal . Setelah itu, Anda hanya perlu membuat migrasi untuk mengembangkan skema Anda.
semoga membantu.
sumber
sequelize.sync()
dan apa yang dilakukannya.Sequelize dapat menjalankan SQL sewenang-wenang secara asinkron .
Yang akan saya lakukan adalah:
mysql_dump -uUSER -pPASS DBNAME > FILE.SQL
var baseSQL = "LOTS OF SQL and it's EVIL because you gotta put \ backslashes before line breakes and \"quotes\" and/or sum" + " one string for each line, or everything will break";
var baseSQL = fs.readFileSync('../seed/baseDump.sql');
module.exports = { up: function (migration, DataTypes) { var baseSQL = "whatever" // I recommend loading a file migration.migrator.sequelize.query(baseSQL); } }
Itu harus mengatur pengaturan database, meskipun hal asinkron mungkin menjadi masalah. Jika itu terjadi, saya akan mencari cara untuk menunda mengembalikan
up
fungsi sequelize sampaiquery
fungsi async selesai.Lebih lanjut tentang mysql_dump: http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html
Lebih lanjut tentang Sequelize Migration: http://sequelize.readthedocs.org/en/latest/docs/migrations/
Selengkapnya tentang Menjalankan SQL dari dalam Sequelize Migration: https://github.com/sequelize/sequelize/issues/313
sumber
Berikut adalah alur kerja saya saat ini. Saya terbuka untuk saran.
Dengan begitu Anda tidak perlu memperbarui tabel migrasi secara manual dan khawatir dengan jari gemuk, tetapi Anda tetap mendapatkan ORM.
sumber
Teman Saya memiliki pertanyaan yang sama dan berhasil memahami cara menggunakannya.
Saya mulai tanpa sekuel ORM karena itu saya sudah memiliki model data.
Saya harus membuat model secara otomatis dengan sequelize-auto dan menghasilkan migrasinya dengan file ini yang Anda buat https://gist.github.com/ahelord/a7a7d293695b71aadf04157f0f7dee64 dan disinkronkan (
{Force: false}
)Ini ada di dev. Saya harus versi model dan migrasi dan menjalankannya setiap kali saya menarik kodenya.
Dalam produksi, server hanya di lantai atas sehingga Anda hanya perlu menjalankan migrasi dan di setiap pengelolaan komit karena Anda akan membuat versi model tanpa menghentikan backend
sumber
Bahkan ada cara yang lebih sederhana (menghindari Sequalize). Yang bunyinya seperti ini:
Anda mengetik perintah di dalam proyek Anda: npm run migrate: new
Ini menciptakan 3 file. File js, dan dua file sql bernama atas dan bawah
Untuk bekerja, silakan lihat modul db-migrate .
Setelah Anda menyiapkannya (yang tidak sulit), mengubah DB Anda sangat mudah dan menghemat banyak waktu.
sumber