Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

renameCollection feature #369

Open
isalciuc opened this issue May 18, 2023 · 3 comments
Open

renameCollection feature #369

isalciuc opened this issue May 18, 2023 · 3 comments

Comments

@isalciuc
Copy link

I didn't find any way to rename a collection in MongoDB using Liquibase

@Ygilany
Copy link

Ygilany commented May 23, 2023

@isalciuc renaming a collection is an adminCommand.

Here's an example for how you can do that

{
  "databaseChangeLog": [
    {
      "changeSet": {
        "id": "2023.05.22.1",
        "author": "Yahya Gilany",
        "comment": "Rename collections",
        "changes": [
          {
            "adminCommand": {
              "command": {
                "$rawJson": {
                  "renameCollection": "database-name.old-collection-name",
                  "to": "database-name.new-collection-name"
                }
              }
            }
          }
        ]
      }
    }
  ]
}

@isalciuc
Copy link
Author

isalciuc commented May 23, 2023

It fails with a not very informative NPE exception:

Caused by: java.lang.NullPointerException: null
at liquibase.ext.mongodb.statement.AdminCommandStatement.run(AdminCommandStatement.java:51)
at liquibase.ext.mongodb.statement.AbstractRunCommandStatement.execute(AbstractRunCommandStatement.java:51)
at liquibase.ext.mongodb.statement.AbstractRunCommandStatement.execute(AbstractRunCommandStatement.java:36)
at liquibase.nosql.executor.NoSqlExecutor.execute(NoSqlExecutor.java:187)

It also requires to run it as admin and to know the database name.

On the other hand, this command doesn't require to run as admin and to know the database name:

db.{source-collection-name}.renameCollection("{new-collection-name}")

@GevorgPetrosyan
Copy link

GevorgPetrosyan commented Jan 26, 2025

To rename a MongoDB collection using Liquibase, you can implement a custom Java class that utilizes the MongoDB Java driver to perform the renaming operation. This approach involves creating a class that implements the liquibase.change.custom.CustomTaskChange interface, allowing you to define custom behavior within your Liquibase changelog.

Create the Custom Java Class:


import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoNamespace;
import com.mongodb.client.model.RenameCollectionOptions;
import liquibase.change.custom.CustomTaskChange;
import liquibase.database.Database;
import liquibase.exception.CustomChangeException;
import liquibase.exception.SetupException;
import liquibase.exception.ValidationErrors;
import liquibase.resource.ResourceAccessor;
import liquibase.ext.mongodb.database.LiquibaseMongoConnection;

public class RenameCollectionChange implements CustomTaskChange {
    private String oldCollectionName;
    private String newCollectionName;

    public void setOldCollectionName(String oldCollectionName) {
        this.oldCollectionName = oldCollectionName;
    }

    public void setNewCollectionName(String newCollectionName) {
        this.newCollectionName = newCollectionName;
    }

    @Override
    public void execute(Database database) throws CustomChangeException {
        try {
            MongoDatabase mongoDatabase = ((LiquibaseMongoConnection) database.getConnection()).getMongoDatabase();
            mongoDatabase.getCollection(oldCollectionName)
                .renameCollection(new MongoNamespace(mongoDatabase.getName(), newCollectionName), new RenameCollectionOptions().dropTarget(false));
        } catch (Exception e) {
            throw new CustomChangeException("Error renaming collection from '" + oldCollectionName + "' to '" + newCollectionName + "'", e);
        }
    }

    @Override
    public String getConfirmationMessage() {
        return "Collection '" + oldCollectionName + "' successfully renamed to '" + newCollectionName + "'";
    }

    @Override
    public void setUp() throws SetupException {
        // No setup required
    }

    @Override
    public void setFileOpener(ResourceAccessor resourceAccessor) {
        // Not needed for this implementation
    }

    @Override
    public ValidationErrors validate(Database database) {
        ValidationErrors validationErrors = new ValidationErrors();
        if (oldCollectionName == null || oldCollectionName.isEmpty()) {
            validationErrors.addError("oldCollectionName is required");
        }
        if (newCollectionName == null || newCollectionName.isEmpty()) {
            validationErrors.addError("newCollectionName is required");
        }
        return validationErrors;
    }
}

In your Liquibase changelog file (e.g., JSON format), reference the custom change class and provide the necessary parameters.

{
  "databaseChangeLog": [
    {
      "changeSet": {
        "id": "rename-collection-1",
        "author": "your-username",
        "changes": [
          {
            "customChange": {
              "class": "your.package.RenameCollectionChange",
              "oldCollectionName": "oldCollectionName",
              "newCollectionName": "newCollectionName"
            }
          }
        ]
      }
    }
  ]
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants