Use Liquibase with MongoDB
MongoDB is a document-oriented NoSQL database. For more information, see MongoDB Documentation.
Supported versions
- 6.X
- 5.X
- MongoDB Atlas
Note: Liquibase does not support the version of MongoDB used with AWS DocumentDB or Azure Cosmos DB .
Prerequisites
- Introduction to Liquibase – Dive into Liquibase concepts.
- Install Liquibase – Download Liquibase on your machine.
- Get Started with Liquibase – Learn how to use Liquibase with an example database.
- init project – Create a new Liquibase project folder to store all Liquibase files.
- How to Apply Your Liquibase Pro License Key – If you use Liquibase Pro, activate your license.
6. Ensure that your MongoDB Pro Extension User Roles are established before continuing.
Install drivers
To use Liquibase and MongoDB, you need four JAR files:
- MongoDB Java Driver Core (
mongodb-driver-core-<version>.jar
) - MongoDB Synchronous Driver (
mongodb-driver-sync-<version>.jar
) - MongoDB BSON (
bson-<version>.jar
) - Liquibase MongoDB extension (
liquibase-mongodb-<version>.jar
)
Place your JAR file(s) in the liquibase/lib
directory.
If you use Maven, you must include the driver JAR as a dependency in your pom.xml
file.
To include the driver JAR in the pom.xml file, use the following code:
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-core</artifactId>
<version>4.9.0</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.9.0</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>bson</artifactId>
<version>4.9.0</version>
</dependency>
<dependency>
<groupId>org.liquibase.ext</groupId>
<artifactId>liquibase-mongodb</artifactId>
<version>4.20.0</version>
</dependency>
Test your connection
- Ensure your MongoDB database is configured. See Install MongoDB for more information.
- Specify the database URL in the
liquibase.properties
file (defaults file), along with other properties you want to set a default value for. Liquibase does not parse the URL. You can either specify the full database connection string or specify the URL using your database's standard JDBC format: - Create a text file called changelog (
.xml
) in your project directory and add a changeset.Note: The use of JSON and YAML changelogs is available in Liquibase version 4.20
XML example 1
- Navigate to your project folder in the CLI and run the Liquibase status command to see whether the connection is successful:
- Make changes to your database with the update command.
- From a database UI tool, ensure that your database contains
myCollection
along with the DATABASECHANGELOG table and DATABASECHANGELOGLOCK table.
url: mongodb://hostname:27017/myDatabase
Note: If you are unsure about how to configure the url
property, refer to Connection String URI Format.
Tip: To apply a Liquibase Pro key to your project, add the following property to the Liquibase properties file: licenseKey: <paste code here>
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.6.xsd
http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-4.6.xsd ">
<changeSet id="1" author="your.name" labels="example-label" context="example-context">
<comment>example-comment</comment>
<createTable tableName="person">
<column name="id" type="int" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="name" type="varchar(50)">
<constraints nullable="false"/>
</column>
<column name="address1" type="varchar(50)"/>
<column name="address2" type="varchar(50)"/>
<column name="city" type="varchar(30)"/>
</createTable>
</changeSet>
<changeSet id="2" author="your.name" labels="example-label" context="example-context">
<comment>example-comment</comment>
<createTable tableName="company">
<column name="id" type="int" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="name" type="varchar(50)">
<constraints nullable="false"/>
</column>
<column name="address1" type="varchar(50)"/>
<column name="address2" type="varchar(50)"/>
<column name="city" type="varchar(30)"/>
</createTable>
</changeSet>
<changeSet id="3" author="other.dev" labels="example-label" context="example-context">
<comment>example-comment</comment>
<addColumn tableName="person">
<column name="country" type="varchar(2)"/>
</addColumn>
</changeSet>
</databaseChangeLog>
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mongodb-pro="http://www.liquibase.org/xml/ns/pro-mongodb"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd
http://www.liquibase.org/xml/ns/pro-mongodb http://www.liquibase.org/xml/ns/pro-mongodb/liquibase-pro-mongodb-latest.xsd">
<changeSet id="1" author="nvoxland" runWith="mongosh">
<mongodb-pro:mongo>
db = db.getSiblingDB( 'mydb' );
db.createCollection('person2');
</mongodb-pro:mongo>
<rollback>
<mongodb-pro:mongo>
db = db.getSiblingDB( 'mydb' );
db.person2.drop();
</mongodb-pro:mongo>
</rollback>
</changeSet>
<changeSet id="2" author="nvoxland" runWith="mongosh">
<mongodb-pro:mongoFile path="scriptFile.js" relativeToChangelogFile="true"/>
<rollback>
<mongodb-pro:mongoFile path="scriptFile-rollback.js" relativeToChangelogFile="true"/>
</rollback>
</changeSet>
<changeSet id="3" author="nvoxland" runWith="mongosh">
<mongodb-pro:mongo>
db.products.insertMany( [
{ item: "card", qty: 15 },
{ item: "envelope", qty: 20 },
{ item: "stamps" , qty: 30 }
] );
</mongodb-pro:mongo>
<rollback>
<mongodb-pro:mongo>
db.products.deleteMany( { } );
</mongodb-pro:mongo>
</rollback>
</changeSet>
</databaseChangeLog>
databaseChangeLog:
- changeSet:
id: 1
author: your.name
labels: example-label
context: example-context
comment: example-comment
changes:
- createTable:
tableName: person
columns:
- column:
name: id
type: int
autoIncrement: true
constraints:
primaryKey: true
nullable: false
- column:
name: name
type: varchar(50)
constraints:
nullable: false
- column:
name: address1
type: varchar(50)
- column:
name: address2
type: varchar(50)
- column:
name: city
type: varchar(30)
- changeSet:
id: 2
author: your.name
labels: example-label
context: example-context
comment: example-comment
changes:
- createTable:
tableName: company
columns:
- column:
name: id
type: int
autoIncrement: true
constraints:
primaryKey: true
nullable: false
- column:
name: name
type: varchar(50)
constraints:
nullable: false
- column:
name: address1
type: varchar(50)
- column:
name: address2
type: varchar(50)
- column:
name: city
type: varchar(30)
- changeSet:
id: 3
author: other.dev
labels: example-label
context: example-context
comment: example-comment
changes:
- addColumn:
tableName: person
columns:
- column:
name: country
type: varchar(2)
JSON example
{
"databaseChangeLog": [
---------------------------CREATE AND DROP COLLECTION---------------------------
{
"changeSet": {
"id": "1",
"author": "as",
"labels": "test_label",
"context": "test_context",
"comment": "test_comment",
"changes": [
{
"createCollection": {
"collectionName": "countries_json"
}
}
]
}
},
{
"changeSet": {
"id": "2",
"author": "as",
"changes": [
{
"dropCollection": {
"collectionName": "towns_json"
}
}
],
"rollback": ""
}
},
---------------------------INSERT ONE---------------------------
{
"changeSet": {
"id": "3",
"author": "as",
"changes": [
{
"insertOne": {
"collectionName": "towns_json",
"document": {
"$rawJson": {
"name": "New York",
"population": 222000000,
"famousFor": [ "the MOMA", "food", "Derek Jeter" ],
"mayor": {
"name": "Bill de Blasio",
"party": "D"
}
}
}
}
}
],
"rollback": ""
}
},
---------------------------INSERT MANY---------------------------
{
"changeSet": {
"id": "4",
"author": "as",
"changes": [
{
"insertMany": {
"collectionName": "countries_json",
"documents": {
"$rawJson": [
{
"_id" : "us",
"name" : "United States",
"exports" : {
"foods" : [
{"name" : "bacon", "tasty" : "true" },
{"name" : "burger"}
]
}
},
{
"_id" : "ca",
"name" : "Canada",
"exports" : {
"foods" : [
{"name" : "bacon", "tasty" : false },
{"name" : "syrup", "tasty" : true}
]
}
},
{
"_id" : "mx",
"name" : "Mexico",
"exports" : {
"foods" : [
{"name" : "salsa", "tasty" : true, "condiment" : true}
]
}
}
]
}
}
}
],
"rollback": {
"runCommand": {
"command": "{ delete: \"countries_json\", deletes: [{q: { }, limit: 0}] }"
}
}
}
},
---------------------------CREATE AND DROP INDEX---------------------------
{
"changeSet": {
"id": "5",
"author": "as",
"changes": [
{
"createIndex": {
"collectionName": "countries_json",
"keys": {
"$rawJson": {
"name": 1,
"type": 1
}
},
"options": {
"$rawJson": {
"unique": true,
"name": "ui_countries_json"
}
}
}
}
]
}
},
{
"changeSet": {
"id": "6",
"author": "as",
"changes": [
{
"dropIndex": {
"collectionName": "countries_json",
"keys": {
"$rawJson": {
"name": 1,
"type": 1
}
},
"options": {
"$rawJson": {
"unique": true,
"name": "ui_countries_json"
}
}
}
}
]
}
},
---------------------------RUN COMMAND---------------------------
{
"changeSet": {
"id": "7",
"author": "as",
"changes": [
{
"runCommand": {
"command": "{ buildInfo: 1 }"
}
}
],
"rollback": ""
}
},
---------------------------ADMIN COMMAND---------------------------
{
"changeSet": {
"id": "8",
"author": "as",
"changes": [
{
"adminCommand": {
"command": "{ buildInfo: 1 }"
}
}
],
"rollback": ""
}
}
]
}
liquibase status --username=test --password=test --changelog-file=<changelog.xml>
Note: You can pass arguments in the CLI or keep them in the Liquibase properties file.
liquibase update --changelog-file=<changelog.xml>
Tip: You can use MongoDB Compass to easily view collections in your database. For example, run the commands use myDatabase
and db.myCollection.find()
.
- createCollection creates a collection with the validator.
<changeSet id="1" author="liquibase">
<ext:createCollection collectionName="myCollection">
<ext:options>
{
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name", "address"],
properties: {
name: {
bsonType: "string",
description: "The Name"
},
address: {
bsonType: "string",
description: "The Address"
}
}
}
},
validationAction: "warn",
validationLevel: "strict"
}
</ext:options>
</ext:createCollection>
</changeSet>
- dropCollection removes a collection or view from the database.
<changeSet id="1" author="liquibase">
<ext:dropCollection collectionName="myCollection"/>
</changeSet>
- createIndex creates an index for a collection.
<changeSet id="1" author="liquibase">
<ext:createIndex collectionName="createIndexTest">
<ext:keys>
{ clientId: 1, type: 1}
</ext:keys>
<ext:options>
{unique: true, name: "ui_tppClientId"}
</ext:options>
</ext:createIndex>
<ext:createIndex collectionName="createIndexNoOptionsTest">
<ext:keys>
{ clientId: 1, type: 1}
</ext:keys>
</ext:createIndex>
</changeSet>
- dropIndex drops an index for a collection by keys.
<changeSet id="1" author="liquibase">
<ext:dropIndex collectionName="createIndexTest">
<ext:keys>
{ clientId: 1, type: 1}
</ext:keys>
<ext:options>
{unique: true, name: "ui_tppClientId"}
</ext:options>
</ext:dropIndex>
<ext:dropIndex collectionName="createIndexNoOptionsTest">
<ext:keys>
{ clientId: 1, type: 1}
</ext:keys>
</ext:dropIndex>
</changeSet>
- insertMany inserts multiple documents into a collection.
<changeSet id="1" author="liquibase">
<ext:insertMany collectionName="insertManyTest1">
<ext:documents>
[
{ id: 2 },
{ id: 3,
address: { nr: 1, ap: 5}
}
]
</ext:documents>
</ext:insertMany>
</changeSet>
- insertOne inserts a single document into a collection.
<changeSet id="1" author="liquibase">
<ext:insertOne collectionName="insertOneTest1">
<ext:document>
{
id: 111
}
</ext:document>
</ext:insertOne>
</changeSet>
<changeSet id="2" author="liquibase">
<ext:insertOne collectionName="insertOneTest2">
<ext:document>
{
id: 2
}
</ext:document>
</ext:insertOne>
<ext:insertOne collectionName="insertOneTest3">
<ext:document>
{
id: 3
}
</ext:document>
</ext:insertOne>
</changeSet>
<changeSet id="3" author="liquibase">
<ext:insertOne collectionName="insertOneTest2">
<ext:document>
{
id: 21323123
}
</ext:document>
</ext:insertOne>
<ext:insertOne collectionName="insertOneTest3">
<ext:document>
{
id: 321321313
}
</ext:document>
</ext:insertOne>
</changeSet>
- runCommand provides a helper to run specified database commands. This is the preferred method to issue database commands as it provides a consistent interface between the shell and drivers.
<changeSet id="1" author="liquibase">
<ext:runCommand>
<ext:command>
{ buildInfo: 1 }
</ext:command>
</ext:runCommand>
</changeSet>
<changeSet id="2" author="liquibase">
<ext:adminCommand>
<ext:command>
{ buildInfo: 1 }
</ext:command>
</ext:adminCommand>
</changeSet>
- adminCommand provides a helper to run specified database commands against the admin database.
<changeSet id="2" author="liquibase">
<ext:adminCommand>
<ext:command>
{ buildInfo: 1 }
</ext:command>
</ext:adminCommand>
</changeSet>
Related links
Created: April 26, 2023