Squelize.js: migraties en synchronisatie gebruiken

Ik ben bijna klaar om mijn project te lanceren. Ik heb grote plannen voor na de lancering en de databasestructuur gaat veranderen — nieuwe kolommen in bestaande tabellen en nieuwe tabellen, en nieuwe associaties met bestaande en nieuwe modellen.

Ik heb het nog niet gehad over migraties in Sequelize, aangezien ik alleen testgegevens heb gehad die ik niet erg vind om ze te wissen telkens als de database verandert.

Hiervoor gebruik ik momenteel sync force: truewanneer mijn app opstart, als ik de modeldefinities heb gewijzigd. Dit verwijdert alle tabellen en maakt ze helemaal opnieuw. Ik zou de optie forcekunnen weglaten om alleen nieuwe tabellen te maken. Maar als bestaande zijn gewijzigd, is dit niet handig.

Dus als ik migraties heb toegevoegd, hoe werken de dingen dan? Het is duidelijk dat ik niet wil dat bestaande tabellen (met gegevens erin) worden weggevaagd, dus sync force: trueis uitgesloten. Op andere apps die ik heb helpen ontwikkelen (Laravel en andere frameworks) voeren we als onderdeel van de implementatieprocedure van de app de opdracht migreren uit om eventuele lopende migraties uit te voeren. Maar in deze apps heeft de allereerste migratie een skeletdatabase, met de database in de staat waarin deze enige tijd vroeg in ontwikkeling was – de eerste alpha-release of wat dan ook. Dus zelfs een app die te laat op het feest komt, kan in één keer op snelheid komen door alle migraties achter elkaar uit te voeren.

Hoe genereer ik zo’n “eerste migratie” in Sequelize? Als ik er geen heb, zal een nieuw exemplaar van de app ergens in de loop van de tijd ofwel geen skeletdatabase hebben om de migraties op uit te voeren, of het zal bij het begin synchroniseren en de database in de nieuwe staat maken met alle de nieuwe tabellen enz., maar wanneer het de migraties probeert uit te voeren, hebben ze geen zin, omdat ze zijn geschreven met de originele database en elke opeenvolgende iteratie in gedachten.

Mijn denkproces: in elke fase moet de initiële database plus elke migratie in volgorde gelijk zijn (plus of minus data) de database die wordt gegenereerd wanneer sync force: truewordt uitgevoerd. Dit komt omdat de modelbeschrijvingen in de code de databasestructuur beschrijven. Dus misschien als er geen migratietabel is, voeren we gewoon synchronisatie uit en markeren we alle migraties als voltooid, ook al zijn ze niet uitgevoerd. Is dit wat ik moet doen (hoe?), of moet Sequelize dit zelf doen, of blaf ik tegen de verkeerde boom? En als ik in het juiste gebied ben, zou er toch zeker een leuke manier moeten zijn om het grootste deel van een migratie automatisch te genereren, gezien de oude modellen (door commit hash? of zou zelfs elke migratie aan een commit kunnen worden gekoppeld? Ik geef toe dat ik denk in een niet-draagbaar git-centrisch universum) en de nieuwe modellen. Het kan de structuur veranderen en de commando’s genereren die nodig zijn om de database van oud naar nieuw en terug te transformeren, en dan kan de ontwikkelaar naar binnen gaan en de nodige aanpassingen maken (bepaalde gegevens verwijderen/overzetten, enz.).

Als ik de sequelize binary uitvoer met het --initcommando, krijg ik een lege migratiemap. Wanneer ik dan sequelize --migrateuitvoer, wordt ik een SequelizeMeta-tabel met niets erin, geen andere tabellen. Uiteraard niet, want dat binaire bestand weet niet hoe hij mijn app moet opstarten en de modellen moet laden.

Ik moet iets missen.

TLDR: hoe stel ik mijn app en de bijbehorende migraties in zodat verschillende instanties van de live-app kunnen worden bijgewerkt, en hoe kan ik een gloednieuwe app zonder verouderde startdatabase instellen?


Antwoord 1, autoriteit 100%

De “eerste migratie” genereren

In jouw geval is de meest betrouwbare manier om het bijna handmatig te doen. Ik raad aan om de tool sequelize-clite gebruiken. De syntaxis is vrij eenvoudig:

sequelize init
...
sequelize model:create --name User --attributes first_name:string,last_name:string,bio:text

Hierdoor ontstaat zowel een model als een migratie. Voeg vervolgens handmatig uw bestaande modellen samen met gegenereerd met sequelize-cli, en doe hetzelfde met migraties. Na dit te hebben gedaan, de database wissen (indien mogelijk) en uitvoeren

sequelize db:migrate

Hiermee worden schema’s voor migraties gemaakt. U hoeft dit slechts één keer te doen om over te schakelen naar het juiste proces van schemaontwikkeling (zonder sync:force, maar met gezaghebbende migraties).

Later, wanneer u het schema moet wijzigen:

  1. Maak een migratie: sequelize migration:create
  2. Schrijf functies op en neer in uw migratiebestand
  3. Volgens uw wijzigingen in het migratiebestand, wijzigt u uw model handmatig
  4. Voer sequelize db:migrate
  5. uit

Migraties uitvoeren op productie

Het is duidelijk dat u niet handmatig kunt ssh-en naar de productieserver en migraties kunt uitvoeren. Gebruik umzug, framework-agnostische migratietool voor Node.JS om lopende migraties uit te voeren voordat de app start.

U kunt als volgt een lijst met in behandeling zijnde/nog niet uitgevoerde migraties krijgen:

umzug.pending().then(function (migrations) {
  // "migrations" will be an Array with the names of
  // pending migrations.
}); 

Voer vervolgens migraties uit (binnen callback). De execute methode is een algemene functie die voor elke gespecificeerde migratie de respectievelijke functie uitvoert:

umzug.execute({
  migrations: ['some-id', 'some-other-id'],
  method: 'up'
}).then(function (migrations) {
  // "migrations" will be an Array of all executed/reverted migrations.
});

En mijn suggestie is om dit te doen voordat de app start en elke keer routes probeert aan te bieden. Zoiets als dit:

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
    });
});

Ik kan dit nu niet proberen, maar op het eerste gezicht zou het moeten werken.

UPD april 2016

Na een jaar nog steeds nuttig, dus ik deel mijn huidige tips. Voor nu installeer ik het pakket sequelize-clizoals vereist liveafhankelijkheid, en wijzig vervolgens de NPM-opstartscripts in package.jsonals volgt:

...
"scripts": {
  "dev": "grunt && sequelize db:migrate && sequelize db:seed:all && node bin/www",
  "start": "sequelize db:migrate && sequelize db:seed:all && node bin/www"
},
...

Het enige dat ik op de productieserver hoef te doen is npm start. Deze opdracht voert alle migraties uit, past alle seeders toe en start de app-server. U hoeft umzug niet handmatig te bellen.


Antwoord 2, autoriteit 18%

Ik heb dit zelf net geleerd, maar ik denk dat ik zou aanraden om nu migraties te gebruiken, zodat je eraan gewend raakt. Ik heb ontdekt dat de beste manier om erachter te komen wat er in de migratie gebeurt, is door naar de sql te kijken in de tabellen die zijn gemaakt door sequelize.sync()en vervolgens de migraties van daaruit op te bouwen.

migrations -c [migration name] 

Maakt het sjabloonmigratiebestand aan in een migratiemap. U kunt het vervolgens vullen met de velden die u moet maken. Dit bestand moet createdAt/updatedAtbevatten, velden die nodig zijn voor associaties, enz.

Voor de eerste aanmaak van een tafel moet down het volgende hebben:

migration.dropTable('MyTable');

Maar volgende updates van de tabelstructuur kunnen dit weglaten en gewoon de tabel wijzigen.

./node_modules/.bin/sequelize --migrate

Een voorbeeld van een creatie ziet er als volgt uit:

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();
  }

Vanaf het begin opnieuw doen:

./node_modules/.bin/sequelize --migrate --undo
./node_modules/.bin/sequelize --migrate

Ik gebruik koffie om een ​​seed-bestand uit te voeren om de tabellen te vullen na:

coffee server/seed.coffee

Dit heeft alleen een aanmaakfunctie die er ongeveer zo uitziet:

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'
    ]
  ]

Vergeet niet om uw sync()uit de index in uw modellen te halen, anders overschrijft het wat de migraties en seed doen.

Documenten staan ​​op http://sequelize.readthedocs.org/en/latest /docs/migrations/natuurlijk. Maar het basisantwoord is dat u alles zelf moet toevoegen om de velden te specificeren die u nodig hebt. Het doet het niet voor jou.


Antwoord 3, autoriteit 13%

Voor ontwikkelingis er nu een optie om de huidige tabellen te synchroniseren door hun structuur te wijzigen. Met behulp van de nieuwste versie van de github repokun je nu synchroniseren met de alterparameter.

Table.sync({alter: true})

Een waarschuwing uit de documenten:

Verandert tabellen zodat ze op modellen passen. Niet aanbevolen voor productiegebruik. Verwijdert gegevens in kolommen die zijn verwijderd of waarvan het type is gewijzigd in het model.


Antwoord 4, autoriteit 8%

Ik heb dit bericht en soortgelijke vragen doorgenomen, maar het beantwoordde het niet echt voor mij. Migraties zijn handig voor het opstarten van lokale databases en voor het bijwerken van gegevens in productie

Ik heb de vraag hier gesteld en ook beantwoord: Workflow voor het afhandelen van sequellen migraties en initialisatie?

TL-DR-versie voor een greenfield-project

  1. Ontwerp uw databaseschema zoals u dat traditioneel zou doen met pure SQL-scripts of als u in plaats daarvan een gui-tool gebruikt
  2. Als je al je 95% van je db-schema hebt voltooid en je bent er tevreden mee, ga je gang en verplaats je het om het vervolg te maken door het hele .sql-bestand te verplaatsen
  3. Maak uw eerste migratie. Voer sequelize init:migrateuit in de map waar uw modelszich bevinden
  4. Maak uw eerste migratiebestand. Voer sequelize migration:generate --name [name_of_your_migration]
  5. uit

  6. Plaats deze code in dat migratiebestand
("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;
`),
};

voer hier de afbeeldingsbeschrijving in

met deze algemene mappenstructuur

voer hier de afbeeldingsbeschrijving in

  1. Je vervolgconfiguratie is nu gesynchroniseerd met je oorspronkelijke databaseschema
  2. als u uw databaseschema wilt bewerken, voert u dit nogmaals uit sequelize migration:generate --name [name_of_your_migration]
  3. Ga je gang en breng hier je wijzigingen aan op de migratiepaden upen down. Dit zijn uw ALTER-instructies om kolomnamen, DELETE, ADD-kolommen enz. te wijzigen
  4. Voer sequelize db:migrate
  5. uit

  6. U wilt dat de modellen worden gesynchroniseerd met de wijzigingen in uw externe database, dus wat u nu kunt doen, is npm install sequelize-auto.
  7. Hiermee wordt het huidige databaseschema in uw database gelezen en automatisch modelbestanden gegenereerd. Gebruik een opdracht die vergelijkbaar is met deze sequelize-auto -o "./models" -d sequelize_auto_test -h localhost -u my_username -p 5432 -x my_password -e postgresgevonden onder https://github.com/sequelize/sequelize-auto

Je kunt git gebruiken om difflogs op je model te zien, er zouden alleen wijzigingen moeten zijn die wijzigingen in het databasemodel weerspiegelen. Als een kanttekening, pas de modelsnooit rechtstreeks aan als u sequelize autogebruikt, omdat dit ze voor u zal genereren. Evenzo moet u uw databaseschema niet langer rechtstreeks met SQL-bestanden wijzigen, mits dit een optie is, aangezien u die .sql-bestanden ook

kunt importeren.

Uw databaseschema is nu up-to-date en u bent officieel overgestapt om alleen databasemigraties te vervolgen.

Alles is versiebeheerd. Dit is de ideale workflow voor database- en backend-ontwikkelaars


Antwoord 5, autoriteit 3%

Nu met de nieuwe sequelize is migratie heel eenvoudig.

Dit is een voorbeeld van wat u kunt doen.

   '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);
                });
        }
    };

Vergeet niet dat u het volgende moet instellen:

"dialectOptions": { "multipleStatements": true }

op databaseconfiguratie.


Antwoord 6, autoriteit 2%

Gebruik versie.
De versie van de applicatie is afhankelijk van de versie van de database.
Als de nieuwe versie een update van een database vereist, maak er dan een migratie voor.

update: ik heb besloten de migratie af te breken (KISS) en script update_db (synchronisatie forse : false) wanneer het nodig is.


Antwoord 7, autoriteit 2%

Squelize kan willekeurige SQL asynchroonuitvoeren.

Wat ik zou doen is:

  • Een migratie genereren (te gebruiken als eerste migratie);
  • Dump je database, zoiets als: mysql_dump -uUSER -pPASS DBNAME > FILE.SQL
  • Plak de volledige dump als tekst (gevaarlijk) of laad een bestand met de volledige dump in Node:
    • 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');
  • Voer deze dump uit op Sequelize Migration:
module.exports = {
  up: function (migration, DataTypes) {
    var baseSQL = "whatever" // I recommend loading a file
    migration.migrator.sequelize.query(baseSQL);
  }
}

Dat zou moeten zorgen voor het opzetten van de database, hoewel het asynchrone probleem een ​​probleem kan worden. Als dat gebeurt, zou ik kijken naar een manier om het retourneren van de upsequelize-functie uit te stellen totdat de asynchrone query-functie is voltooid.

Meer over mysql_dump: http://dev.mysql.com /doc/refman/5.1/en/mysqldump.html
Meer over Sequelize Migrations: http://sequelize.readthedocs.org/en/latest/ docs/migrations/
Meer over SQL uitvoeren vanuit Sequelize Migration: https://github.com/sequelize/sequelize/issues /313


Antwoord 8

Een beetje laat, en na het lezen van de documentatie, heb je die eerste migratie waar je het over hebt niet nodig. Het enige wat u hoeft te doen is syncaan te roepen om de tabellen te maken.

sequelize.sync()

U kunt ook een eenvoudige modelsynchronisatie uitvoeren door zoiets te doen:

Project.sync()maar ik denk dat sequelize.sync()een nuttiger algemeen geval is voor uw project (zolang u de goede modellen importeert op starttijd).

(overgenomen van http://sequelizejs.com/docs/latest/models#database -synchronisatie)

Hiermee worden alle initiëlestructuren gemaakt. Daarna hoeft u alleen nog maar migraties te maken om uw schema’s te laten evolueren.

hoop dat het helpt.


Antwoord 9

Hier is mijn huidige workflow. Ik sta open voor suggesties.

  1. Stel vervolg op om tabellen te maken die niet bestaan
  2. Stel vervolg op
    om alle tabellen te laten vallen en opnieuw te maken in een lege database met de naam
    _blank
  3. Gebruik een mysql-tool om te vergelijken
    _blank en en synchroniseer wijzigingen met
    dat gereedschap. Nog steeds op zoek naar een betaalbare tool die dit kan doen op
    Mac. MySql workbench ziet eruit alsof je een model kunt importeren uit een
    bestaand schema en vervolgens het schema synchroniseren. Proberen uit te vinden hoe
    doe dit via de opdrachtregel om het gemakkelijk te maken.

Op die manier hoeft u de migratietabel niet handmatig bij te werken en hoeft u zich geen zorgen te maken over dikke vingers, maar krijgt u toch een ORM.


Antwoord 10

Vriend Ik had dezelfde vraag en wist hoe ik ze moest gebruiken.

Ik ben begonnen zonder ORM sequelize, daarom had ik al een datamodel.
Ik moest de modellen automatisch genereren met sequelize-auto en hun migraties genereren met dit bestand dat je maakt https:/ /gist.github.com/ahelord/a7a7d293695b71aadf04157f0f7dee64en gesynchroniseerd ({Force: false})
Dit is in dev. Ik zou het model en de migraties moeten aanpassen en uitvoeren elke keer dat ik de code haal.

In productie is de server alleen boven, dus je hoeft alleen migraties uit te voeren en in elke commit te beheren, aangezien je het model versiert zonder de backend te stoppen


Antwoord 11

Er is een nog eenvoudigere manier (het vermijden van Sequalize). Dat gaat als volgt:

  1. U typt een commando in uw project: npm run migreren:new

  2. Hiermee worden 3 bestanden gemaakt. Een js-bestand en twee sql-bestanden met de namen omhoog en omlaag

  3. U plaatst uw SQL-instructie in die bestanden, wat pure sql is
  4. Vervolgens typt u: npm run migreren:upof npm run migreren:down

Om dit te laten werken, raadpleegt u de db-migratemodule.

Als je het eenmaal hebt ingesteld (wat niet moeilijk is), is het wijzigen van je DB heel eenvoudig en bespaart het veel tijd.

Other episodes