Skip to content

Instantly share code, notes, and snippets.

@Podbrushkin
Created November 23, 2023 15:01
Show Gist options
  • Save Podbrushkin/3f16feb9b9da22ab27ee2878c38633aa to your computer and use it in GitHub Desktop.
Save Podbrushkin/3f16feb9b9da22ab27ee2878c38633aa to your computer and use it in GitHub Desktop.
Neo4j Embedded with Apoc plugin, export database to Cypher file
package myapp;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import org.neo4j.configuration.connectors.BoltConnector;
import org.neo4j.configuration.helpers.SocketAddress;
import org.neo4j.dbms.api.DatabaseManagementServiceBuilder;
import org.neo4j.dbms.api.DatabaseManagementService;
import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.TransactionContext;
import org.neo4j.exceptions.KernelException;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.kernel.api.procedure.GlobalProcedures;
import org.neo4j.kernel.internal.GraphDatabaseAPI;
import apoc.ApocConfig;
import static org.neo4j.configuration.GraphDatabaseSettings.DEFAULT_DATABASE_NAME;
import static apoc.ApocConfig.apocConfig;
public class GraphApplication {
public static void main(String... a) throws IOException {
// This is the db itself, should be long-lived
var graphDb = new DatabaseManagementServiceBuilder(Path.of("target", "mydb"))
.setConfig(BoltConnector.enabled, true)
.setConfig(BoltConnector.listen_address, new SocketAddress("localhost", 7687))
.setConfig(BoltConnector.encryption_level, BoltConnector.EncryptionLevel.DISABLED)
.build();
var db = graphDb.database(DEFAULT_DATABASE_NAME);
registerProcedure(db,
apoc.export.cypher.ExportCypher.class);
// src:
// https://github.com/neo4j/apoc/blob/ed198fadfec318613de6bc6bd35276504915854c/core/src/test/java/apoc/export/BigGraphTest.java#L77
apocConfig().setProperty(ApocConfig.APOC_EXPORT_FILE_ENABLED, true);
registerShutdownHook(graphDb);
// You could also use the graph database api and skip using bolt.
// The advantage of using build also in an embedded scenario: You can switch to
// a server with ease.
// Same goes for the driver with the connection pool
// The session itself is short-lived
try (
var driver = GraphDatabase.driver("bolt://localhost:7687", AuthTokens.none());
var session = driver.session()) {
session.executeWrite(t -> t.run(
"CREATE (p:Person {name: 'Arnold Schwarzenegger'}) - [:ACTED_IN] -> (:Movie {title: 'The Terminator'})")
.consume().counters().nodesCreated());
var movies = session.executeRead(GraphApplication::findMovieAndTheirActors);
movies.forEach(System.out::println);
// src:
// https://neo4j.com/labs/apoc/4.1/export/cypher/#export-cypher-neo4j-browser
var query = """
CALL apoc.export.cypher.all("all-plain.cypher", {
format: "plain",
useOptimizations: {type: "UNWIND_BATCH", unwindBatchSize: 20}
})
""";
session.executeRead(t -> t.run(query).consume());
System.out.println("Dump of database has been created in /target/mydb/");
}
// graphDb.shutdown();
}
public static void registerProcedure(GraphDatabaseService db, Class<?>... procedures) {
GlobalProcedures globalProcedures = ((GraphDatabaseAPI) db).getDependencyResolver()
.resolveDependency(GlobalProcedures.class);
for (Class<?> procedure : procedures) {
try {
globalProcedures.registerProcedure(procedure);
globalProcedures.registerFunction(procedure);
globalProcedures.registerAggregationFunction(procedure);
} catch (KernelException e) {
throw new RuntimeException("while registering " + procedure, e);
}
}
}
private static void registerShutdownHook(final DatabaseManagementService managementService) {
// Registers a shutdown hook for the Neo4j instance so that it
// shuts down nicely when the VM exits (even if you "Ctrl-C" the
// running application).
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.out.println("Shutdown requested, please wait 3 seconds...");
managementService.shutdown();
System.out.println("Shutdown completed successfully.");
}
});
}
record Person(String name) {
}
record Movie(String title, List<Person> actedIn) {
}
static List<Movie> findMovieAndTheirActors(TransactionContext tx) {
var query = """
MATCH (m:Movie) <- [:ACTED_IN] - (p:Person)
WHERE m.title =~ $movieTitle
RETURN m.title AS title, collect(p.name) AS actors
""";
return tx.run(query, Map.of("movieTitle", ".*The.*")).list(r -> {
var actors = r.get("actors").asList(v -> new Person(v.asString()));
return new Movie(r.get("title").asString(), actors);
});
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>somegroup</groupId>
<artifactId>someapp</artifactId>
<version>1.0-SNAPSHOT</version>
<description>
Run it with `mvn clean compile exec:java` and you'll get a cypher dump file in `target/mydb/`.
</description>
<properties>
<maven.compiler.release>17</maven.compiler.release>
<neo4j.version>5.13.0</neo4j.version>
<exec.mainClass>myapp.GraphApplication</exec.mainClass>
</properties>
<dependencies>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>${neo4j.version}</version>
</dependency>
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>${neo4j.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.neo4j.procedure/apoc-core -->
<dependency>
<groupId>org.neo4j.procedure</groupId>
<artifactId>apoc-core</artifactId>
<version>${neo4j.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.neo4j.procedure/apoc-extended -->
<!-- This one not necessary -->
<!-- <dependency>
<groupId>org.neo4j.procedure</groupId>
<artifactId>apoc-extended</artifactId>
<version>${neo4j.version}</version>
</dependency> -->
<!-- https://mvnrepository.com/artifact/org.neo4j.procedure/apoc-common -->
<dependency>
<groupId>org.neo4j.procedure</groupId>
<artifactId>apoc-common</artifactId>
<version>${neo4j.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
</plugin>
</plugins>
</build>
</project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment