migrate-mongo

repository·master·Indexed 21 days ago

https://github.com/seppevs/migrate-mongo

A database migration tool for MongoDB in Node.js (version 14.0.7) that allows developers to version control database schema and data changes using timestamped migration scripts. It provides a CLI and programmatic API to initialize projects, create migrations, and execute 'up' and 'down' operations. Supports Node.js >= 20.0.0, MongoDB 4.x through 7.x, and both CommonJS and ES modules.

Tokens
4.3K
Snippets
23
Records
23
Agent score
76%

What's inside migrate-mongo

  1. Use MongoDB Transactions in migration scripts

    master

    To use the MongoDB Transaction API, you must be using MongoDB 4.0+ and migrate-mongo 7.0.0+.

    migrate-mongo passes a client argument (an instance of MongoClient) as the second argument to your up and down functions. You can use this client to call startSession() and wrap your operations in withTransaction().

    module.exports = {
      async up(db, client) {
        const session = client.startSession();
        try {
            await session.withTransaction(async () => {
                await db.collection('albums').updateOne({artist: 'The Beatles'}, {$set: {blacklisted: true}}, {session});
                await db.collection('albums').updateOne({artist: 'The Doors'}, {$set: {stars: 5}}, {session});
            });
        } finally {
          await session.endSession();
        }
      },
    
      async down(db, client) {
        const session = client.startSession();
        try {
            await session.withTransaction(async () => {
                await db.collection('albums').updateOne({artist: 'The Beatles'}, {$set: {blacklisted: false}}, {session});
                await db.collection('albums').updateOne({artist: 'The Doors'}, {$set: {stars: 0}}, {session});
            });
        } finally {
          await session.endSession();
        }
      },
    };
  2. Implement up and down migration functions

    master

    Migration files export an object with up and down functions.

    • up(db, client): Logic to apply the migration.
    • down(db, client): Logic to revert the migration.

    db is the official MongoDB Db object, and client is the MongoClient instance.

    You can implement these functions by returning a Promise or by using async/await (recommended).

    module.exports = {
      async up(db) {
        await db.collection('albums').updateOne({artist: 'The Beatles'}, {$set: {blacklisted: true}});
        await db.collection('albums').updateOne({artist: 'The Doors'}, {$set: {stars: 5}});
      },
    
      async down(db) {
        await db.collection('albums').updateOne({artist: 'The Doors'}, {$set: {stars: 0}});
        await db.collection('albums').updateOne({artist: 'The Beatles'}, {$set: {blacklisted: false}});
      },
    };
  3. Manage migration execution (up, down, status)

    master

    Use the following commands to control the state of your database:

    • Check status: migrate-mongo status shows which migrations are PENDING or have been applied (with timestamp).
    • Apply migrations: migrate-mongo up runs all pending migrations in order. It stops if an error occurs.
    • Revert migrations: migrate-mongo down reverts only the single last applied migration.
    • Revert block: migrate-mongo down -b (or --block) reverts all scripts belonging to the last migration block.
    # Check status
    $ migrate-mongo status
    
    # Run pending migrations
    $ migrate-mongo up
    
    # Undo last migration
    $ migrate-mongo down
    
    # Undo all scripts in the last migration block
    $ migrate-mongo down -b
  4. Initialize a new migrate-mongo project

    master

    To start using migrate-mongo, create a directory for your migrations and run the init command. This generates a migrate-mongo-config.js file and a migrations directory.

    By default, it creates a CommonJS project. To use ES modules, use the -m esm flag.

    $ mkdir albums-migrations
    $ cd albums-migrations
    $ migrate-mongo init
    
    # For ES modules:
    $ migrate-mongo init -m esm
  5. Create a new migration script

    master

    Generate a new migration file by running migrate-mongo create [description]. The file will be created in your configured migrationsDir with a timestamped filename.

    Tip: To override the default boilerplate content created by the create command, place a file named sample-migration.js in your migrations directory.

    $ migrate-mongo create blacklist_the_beatles
    # Creates: migrations/20160608155948-blacklist_the_beatles.js
  6. Initialize a project with ESM (ECMAScript Modules)

    master

    To use ESM instead of CommonJS, you must perform two steps:

    1. Initialize the project with the -m esm flag:
      migrate-mongo init -m esm
    2. Ensure your package.json contains "type": "module".

    When using ESM, migration files created via migrate-mongo create will be generated using ESM syntax.

    $ migrate-mongo init -m esm
    $ npm init --yes
    # Then add "type": "module" to package.json
  7. Enable file hash tracking to re-run updated migrations

    master

    By default, migrate-mongo treats scripts as immutable. If you want to be able to re-run a migration if its content changes, set useFileHash: true in your configuration file.

    Warning: When this is enabled, every script must be written to be idempotent (safe to run multiple times), as migrate-mongo will execute a file with the same name again if its hash has changed.

    // In your migrate-mongo-config.js
    useFileHash: true
  8. Configure migrate-mongo

    master

    After initialization, edit the migrate-mongo-config.js file to specify your MongoDB connection details. You must provide at least a url (and optionally a databaseName).

    Key configuration options:

    • mongodb.url: The MongoDB connection string.
    • mongodb.databaseName: The name of the database (can also be included in the URL).
    • migrationsDir: Path to the migrations directory (default: "migrations").
    • changelogCollectionName: Collection where applied changes are stored (default: "changelog").
    • lockCollectionName: Collection used for locking (default: "changelog_lock").
    • lockTtl: TTL index value for the lock in seconds (0 to disable).
    const config = {
      mongodb: {
        url: "mongodb://localhost:27017",
        databaseName: "YOURDATABASENAME",
        options: {}
      },
      migrationsDir: "migrations",
      changelogCollectionName: "changelog",
      lockCollectionName: "changelog_lock",
      lockTtl: 0,
      migrationFileExtension: ".js",
      useFileHash: false,
      moduleSystem: 'commonjs',
    };
    
    module.exports = config;
  9. Override configuration programmatically with config.set()

    master

    If you want to bypass the migrate-mongo-config.js file and provide configuration directly in your code, use config.set(yourConfigObject). This must be called at the very beginning of your program execution.

    const { config, up } = require('migrate-mongo');
    
    const myConfig = {
        mongodb: {
            url: "mongodb://localhost:27017/mydatabase",
        },
        migrationsDir: "migrations",
        changelogCollectionName: "changelog",
        migrationFileExtension: ".js"
    };
    
    config.set(myConfig);
    
    // Now you can use other API methods
    // await up(db, client);
  10. Programmatic API Reference

    master

    The following functions are exported by migrate-mongo for programmatic usage:

    • init(): Initializes a new project (creates config and migrations dir).
    • create(description): Creates a new migration file. Returns Promise<fileName>.
    • database.connect(): Connects to MongoDB using config settings. Returns Promise<{db: MongoDb, client: MongoClient}>.
    • config.read(): Reads the configuration object. Returns Promise<JSON>.
    • config.set(yourConfigObject): Overrides the config file with a provided object. Should be called at the start of your program.
    • up(db, client): Applies all pending migrations. Returns Promise<Array<fileName>>.
    • down(db, client): Reverts the last applied migration. Returns Promise<Array<fileName>>.
    • status(db): Checks migration status. Returns Promise<Array<{ fileName, appliedAt }>>.
    • client.close(): Closes the database connection.
    const {
      init,
      create,
      database,
      config,
      up,
      down,
      status
    } = require('migrate-mongo');