apoc.bolt.BoltConnection Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of apoc Show documentation
Show all versions of apoc Show documentation
A collection of useful Neo4j Procedures
package apoc.bolt;
import apoc.result.RowResult;
import apoc.result.VirtualNode;
import apoc.result.VirtualRelationship;
import apoc.util.MissingDependencyException;
import apoc.util.UriResolver;
import apoc.util.Util;
import org.apache.commons.lang3.StringUtils;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.Record;
import org.neo4j.driver.Result;
import org.neo4j.driver.Session;
import org.neo4j.driver.Transaction;
import org.neo4j.driver.Value;
import org.neo4j.driver.internal.InternalEntity;
import org.neo4j.driver.internal.InternalPath;
import org.neo4j.driver.summary.SummaryCounters;
import org.neo4j.driver.types.Node;
import org.neo4j.driver.types.Path;
import org.neo4j.driver.types.Relationship;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Label;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.internal.helpers.collection.Iterators;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static apoc.util.MapUtil.map;
public class BoltConnection {
private final BoltConfig config;
private final UriResolver resolver;
public BoltConnection(BoltConfig config, UriResolver resolver) {
this.config = config;
this.resolver = resolver;
}
public static BoltConnection from(Map config, String url) throws URISyntaxException {
try {
final UriResolver resolver = new UriResolver(url, "bolt");
resolver.initialize();
return new BoltConnection(new BoltConfig(config), resolver);
} catch (NoClassDefFoundError e) {
throw new MissingDependencyException("Cannot find the needed jar into the plugins folder in order to use . \n" +
"Please see the documentation: https://neo4j.com/labs/apoc/4.4/database-integration/bolt-neo4j/#_install_dependencies");
}
}
// methods from Bolt.java
public Stream loadFromSession(String statement, Map params) {
return withDriverAndSession(session -> {
if (config.isAddStatistics()) {
Result statementResult = session.run(statement, params);
SummaryCounters counters = statementResult.consume().counters();
return Stream.of(new RowResult(toMap(counters)));
} else
return getRowResultStream(config.isVirtual(), session, params, statement);
});
}
public Stream loadFromLocal(String localStatement, String remoteStatement, GraphDatabaseService db) {
return withDriverAndSession(session -> {
try (org.neo4j.graphdb.Transaction tx = db.beginTx()) {
final org.neo4j.graphdb.Result localResult = tx.execute(localStatement, config.getLocalParams());
String withColumns = "WITH " + localResult.columns().stream()
.map(c -> "$" + c + " AS " + c)
.collect(Collectors.joining(", ")) + "\n";
Map nodesCache = new HashMap<>();
List response = new ArrayList<>();
while (localResult.hasNext()) {
final Result statementResult;
Map row = localResult.next();
if (config.isStreamStatements()) {
final String statement = (String) row.get("statement");
if (StringUtils.isBlank(statement)) continue;
final Map params = Collections.singletonMap("params", row.getOrDefault("params", Collections.emptyMap()));
statementResult = session.run(statement, params);
} else {
statementResult = session.run(withColumns + remoteStatement, row);
}
if (config.isStreamStatements()) {
response.add(new RowResult(toMap(statementResult.consume().counters())));
} else {
response.addAll(
statementResult.stream()
.map(record -> buildRowResult(record, nodesCache, config.isVirtual()))
.collect(Collectors.toList())
);
}
}
return response.stream();
}
});
}
private Stream withDriverAndSession(Function> funSession) {
return withDriver(driver -> withSession(driver,funSession));
}
private Stream withDriver(Function> function) {
Driver driver = GraphDatabase.driver(resolver.getConfiguredUri(), resolver.getToken(), config.getDriverConfig());
return function.apply(driver).onClose(driver::close);
}
private Stream withSession(Driver driver, Function> function) {
Session session = driver.session(config.getSessionConfig());
return function.apply(session).onClose(session::close);
}
private Stream withTransaction(Session session, Function> function) {
Transaction transaction = session.beginTransaction();
return function.apply(transaction).onClose(transaction::commit).onClose(transaction::close);
}
private RowResult buildRowResult(Record record, Map nodesCache, boolean virtual) {
return new RowResult(record.asMap(value -> {
Object entity = value.asObject();
if (entity instanceof Node) return toNode(entity, virtual, nodesCache);
if (entity instanceof Relationship) return toRelationship(entity, virtual, nodesCache);
if (entity instanceof Path) return toPath(entity, virtual, nodesCache);
return entity;
}));
}
private Stream getRowResultStream(boolean virtual, Session session, Map params, String statement) {
Map nodesCache = new HashMap<>();
return withTransaction(session, tx -> {
ClosedAwareDelegatingIterator iterator = new ClosedAwareDelegatingIterator(tx.run(statement, params));
return Iterators.stream(iterator).map(record -> buildRowResult(record, nodesCache, virtual));
});
}
private Object toNode(Object value, boolean virtual, Map nodesCache) {
Value internalValue = ((InternalEntity) value).asValue();
Node node = internalValue.asNode();
if (virtual) {
List