This package allows to perform versioned migrations on your MongoDB using mongo-go-driver. Inspired by go-pg migrations.
- Golang >= 1.22
go get -v -u github.com/xakep666/mongo-migrate
- Create a package with migration files.
File name should be like
<version>_<description>.go
.
1_add-my-index.go
package migrations
import (
"context"
"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.MustRegister(func(ctx context.Context, db *mongo.Database) error {
opt := options.Index().SetName("my-index")
keys := bson.D{{Key: "my-key", Value: 1}}
model := mongo.IndexModel{Keys: keys, Options: opt}
_, err := db.Collection("my-coll").Indexes().CreateOne(ctx, model)
if err != nil {
return err
}
return nil
}, func(ctx context.Context, db *mongo.Database) error {
_, err := db.Collection("my-coll").Indexes().DropOne(ctx, "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)
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri))
if err != nil {
return nil, err
}
db := client.Database(database)
migrate.SetDatabase(db)
if err := migrate.Up(ctx, migrate.AllAvailable); err != nil {
return nil, err
}
return db, nil
}
- 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)
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
err = mongo.Connect(ctx, opt)
if err != nil {
return nil, err
}
db = client.Database(database)
m := migrate.NewMigrate(db, migrate.Migration{
Version: 1,
Description: "add my-index",
Up: func(ctx context.Context, 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(ctx, model)
if err != nil {
return err
}
return nil
},
Down: func(ctx context.Context, db *mongo.Database) error {
_, err := db.Collection("my-coll").Indexes().DropOne(ctx, "my-index")
if err != nil {
return err
}
return nil
},
})
if err := m.Up(ctx, migrate.AllAvailable); err != nil {
return nil, err
}
return db, nil
}
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.
mongo-migrate project is licensed under the terms of the MIT license. Please see LICENSE in this repository for more details.