Skip to content
Versioned migrations for MongoDB.
Go
Branch: master
Clone or download
xakep666 Merge pull request #6 from Yoone/master
Fixed issue related to "no documents in result" on first run
Latest commit b6296c1 Aug 26, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.gitignore First commit. Add basic functions (untested). Aug 21, 2018
.travis.yml Verbose tests in travis.yml Aug 22, 2018
1_global_migrate_test.go feat(driver): updated the mongo driver from mgo to mongo-driver May 26, 2019
1_sample_data_test.go feat(driver): updated the mongo driver from mgo to mongo-driver May 26, 2019
2_sample_index_test.go feat(driver): updated the mongo driver from mgo to mongo-driver May 26, 2019
LICENSE Create LICENSE Aug 21, 2018
README.md docs: added indentation and updated driver details May 26, 2019
bad_migration_file_test.go
global_migrate.go docs: updated indentation for godoc Jun 2, 2019
global_migrate_integration_test.go feat(driver): updated the mongo driver from mgo to mongo-driver May 26, 2019
go.mod feat(driver): updated the mongo driver from mgo to mongo-driver May 26, 2019
go.sum feat(driver): updated the mongo driver from mgo to mongo-driver May 26, 2019
migrate.go Version: Changed error check to switch Aug 26, 2019
migration.go feat(driver): updated the mongo driver from mgo to mongo-driver May 26, 2019
migration_integration_test.go Migration test: added error check in TestMain Aug 26, 2019
migration_test.go Add unit tests. Aug 21, 2018
util.go Add unit tests. Aug 21, 2018
util_test.go Add unit tests. Aug 21, 2018

README.md

Versioned migrations for MongoDB

Build Status codecov Go Report Card GoDoc License: MIT

This package allows to perform versioned migrations on your MongoDB using mongo-go-driver. Inspired by go-pg migrations.

Table of Contents

Prerequisites

  • Golang >= 1.10 or Vgo

Installation

go get -v -u github.com/xakep666/mongo-migrate

Usage

Use case #1. Migrations in files.

  • Create a package with migration files. File name should be like <version>_<description>.go.

1_add-my-index.go

package migrations

import (
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	migrate "github.com/xakep666/mongo-migrate"
)

func init() {
	migrate.Register(func(db *mongo.Database) error {
		opt := options.Index().SetName("my-index")
		keys := bson.D{{"my-key", 1}}
		model := mongo.IndexModel{Keys: keys, Options: opt}
		_, err := db.Collection("my-coll").Indexes().CreateOne(context.TODO(), model)
		if err != nil {
			return err
		}

		return nil
	}, func(db *mongo.Database) error {
		_, err := db.Collection("my-coll").Indexes().DropOne(context.TODO(), "my-index")
		if err != nil {
			return err
		}
		return nil
	})
}
  • Import it in your application.
import (
    ...
    migrate "github.com/xakep666/mongo-migrate"
    _ "path/to/migrations_package" // database migrations
    ...
)
  • Run migrations.
func MongoConnect(host, user, password, database string) (*mongo.Database, error) {
	uri := fmt.Sprintf("mongodb://%s:%s@%s:27017", user, password, host)
	opt := options.Client().ApplyURI(uri)
	client, err := mongo.NewClient(opt)
	if err != nil {
		return nil, err
	}
	ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
	defer cancel()
	err = client.Connect(ctx)
	if err != nil {
		return nil, err
	}
	db = client.Database(database)
	migrate.SetDatabase(db)
	if err := migrate.Up(migrate.AllAvailable); err != nil {
		return nil, err
	}
	return db, nil
}

Use case #2. Migrations in application code.

  • Just define it anywhere you want and run it.
func MongoConnect(host, user, password, database string) (*mongo.Database, error) {
	uri := fmt.Sprintf("mongodb://%s:%s@%s:27017", user, password, host)
	opt := options.Client().ApplyURI(uri)
	client, err := mongo.NewClient(opt)
	if err != nil {
		return nil, err
	}
	ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
	defer cancel()
	err = client.Connect(ctx)
	if err != nil {
		return nil, err
	}
	db = client.Database(database)
	m := migrate.NewMigrate(db, migrate.Migration{
		Version: 1,
		Description: "add my-index",
		Up: func(db *mongo.Database) error {
			opt := options.Index().SetName("my-index")
			keys := bson.D{{"my-key", 1}}
			model := mongo.IndexModel{Keys: keys, Options: opt}
			_, err := db.Collection("my-coll").Indexes().CreateOne(context.TODO(), model)
			if err != nil {
				return err
			}

			return nil
		},
		Down: func(db *mongo.Database) error {
			_, err := db.Collection("my-coll").Indexes().DropOne(context.TODO(), "my-index")
			if err != nil {
				return err
			}
			return nil
		},
	})
	if err := m.Up(migrate.AllAvailable); err != nil {
		return nil, err
	}
	return db, nil
}

How it works?

This package creates a special collection (by default it`s name is "migrations") for versioning. In this collection stored documents like

{
    "_id": "<mongodb-generated id>",
    "version": 1,
    "description": "add my-index",
    "timestamp": "<when applied>"
}

Current database version determined as version from latest inserted document.

You can change collection name using SetMigrationsCollection methods. Remember that if you want to use custom collection name you need to set it before running migrations.

License

mongo-migrate project is licensed under the terms of the MIT license. Please see LICENSE in this repository for more details.

You can’t perform that action at this time.