marianozunino / morpheus

Morpheus is database migration tool for Neo4j written in Typescript.
MIT License
18 stars 4 forks source link

Support multiple databases #5

Open marianozunino opened 2 years ago

marianozunino commented 2 years ago

I would like to specify to which database apply the migrations.

michael-simons commented 2 years ago

Relevant bits:

Getting the chain of applied migrations

String query = ""
            + "MATCH p=(b:__Neo4jMigration {version:'BASELINE'}) - [r:MIGRATED_TO*] -> (l:__Neo4jMigration) \n"
            + "WHERE coalesce(b.migrationTarget,'<default>') = coalesce($migrationTarget,'<default>') AND NOT (l)-[:MIGRATED_TO]->(:__Neo4jMigration)\n"
            + "RETURN p";

Here: Assume a property with value <default> if there's none, so that it stays compatible with other migrations not having it said

Cleaning all migration data

String query = ""
            + "MATCH (n:__Neo4jMigration) "
            + "WITH n, coalesce(n.migrationTarget, '<default>') as migrationTarget "
            + "WHERE (migrationTarget = coalesce($migrationTarget,'<default>') OR $all)"
            + "DETACH DELETE n "
            + "RETURN DISTINCT migrationTarget "
            + "ORDER BY migrationTarget ASC ";

Getting the last applied migration

"MATCH (l:__Neo4jMigration) WHERE coalesce(l.migrationTarget,'<default>') = coalesce($migrationTarget,'<default>') AND NOT (l)-[:MIGRATED_TO]->(:__Neo4jMigration) RETURN l",
michael-simons commented 2 years ago

Recording a new migration (sorry, Java)

    private MigrationVersion recordApplication(String neo4jUser, MigrationVersion previousVersion, Migration appliedMigration,
        long executionTime) {

        try (Session session = context.getSchemaSession()) {

            Optional<String> migrationTarget = context.getConfig().getMigrationTargetIn(context);
            Map<String, Object> parameters = new HashMap<>();
            parameters.put("neo4jUser", neo4jUser);
            parameters.put("previousVersion", previousVersion.getValue());
            parameters.put("appliedMigration", toProperties(appliedMigration));
            parameters.put("installedBy", config.getOptionalInstalledBy().map(Values::value).orElse(Values.NULL));
            parameters.put("executionTime", executionTime);
            parameters.put(PROPERTY_MIGRATION_TARGET, migrationTarget.orElse(null));

            session.writeTransaction(t -> {
                String mergeOrMatchAndMaybeCreate;
                if (migrationTarget.isPresent()) {
                    mergeOrMatchAndMaybeCreate = "MERGE (p:__Neo4jMigration {version: $previousVersion, migrationTarget: $migrationTarget}) ";
                } else {
                    Result result = t.run(
                        "MATCH (p:__Neo4jMigration {version: $previousVersion}) WHERE p.migrationTarget IS NULL RETURN id(p) AS id",
                        Values.parameters("previousVersion", previousVersion.getValue()));
                    if (result.hasNext()) {
                        parameters.put("id", result.single().get("id").asLong());
                        mergeOrMatchAndMaybeCreate = "MATCH (p) WHERE id(p) = $id WITH p ";
                    } else {
                        mergeOrMatchAndMaybeCreate = "CREATE (p:__Neo4jMigration {version: $previousVersion}) ";
                    }
                }

                return t.run(
                        mergeOrMatchAndMaybeCreate
                            + "CREATE (c:__Neo4jMigration) SET c = $appliedMigration, c.migrationTarget = $migrationTarget "
                            + "MERGE (p) - [:MIGRATED_TO {at: datetime({timezone: 'UTC'}), in: duration( {milliseconds: $executionTime} ), by: $installedBy, connectedAs: $neo4jUser}] -> (c)",
                        parameters)
                    .consume();
            });
        }

        return appliedMigration.getVersion();
    }
ksmv-7 commented 1 year ago

Hello @marianozunino ! We have been using the morpheus4j since around end of November 2022 and it is a very neat npm package. I have the same requirement for my project - we have to run multiple neo4j instances, hence we would need to apply the migration to all of them. Do you still plan on adding this feature?

marianozunino commented 1 year ago

Hey @ksmv-7, not sure if I'm following you. If you are running multiple instances that's one thing.

This ticket is for support multiple databases in the same instance (for which you need the Enterprise Edition doc) and that's the reason why I haven't worked on this one.

ksmv-7 commented 1 year ago

Oh, sorry, my mistake. I would open another issue, then