use of apoc.Description in project neo4j-apoc-procedures by neo4j-contrib.
the class Grouping method group.
@Procedure
@Description("Group all nodes and their relationships by given keys, create virtual nodes and relationships for the summary information, you can provide an aggregations map [{kids:'sum',age:['min','max','avg'],gender:'collect'},{`*`,'count'}]")
public Stream<GraphResult> group(@Name("labels") List<String> labels, @Name("groupByProperties") List<String> groupByProperties, @Name(value = "aggregations", defaultValue = "[{\"*\":\"count\"},{\"*\":\"count\"}]") List<Map<String, Object>> aggregations) {
String[] keys = groupByProperties.toArray(new String[groupByProperties.size()]);
Map<String, List<String>> nodeAggNames = (aggregations.size() > 0) ? toStringListMap(aggregations.get(0)) : emptyMap();
String[] nodeAggKeys = keyArray(nodeAggNames, ASTERISK);
Map<String, List<String>> relAggNames = (aggregations.size() > 1) ? toStringListMap(aggregations.get(1)) : emptyMap();
String[] relAggKeys = keyArray(relAggNames, ASTERISK);
Map<NodeKey, Set<Node>> grouped = new ConcurrentHashMap<>();
Map<NodeKey, Node> virtualNodes = new ConcurrentHashMap<>();
Map<RelKey, Relationship> virtualRels = new ConcurrentHashMap<>();
List<Future> futures = new ArrayList<>(1000);
ExecutorService pool = Pools.DEFAULT;
for (String labelName : labels) {
Label label = Label.label(labelName);
Label[] singleLabel = { label };
try (ResourceIterator<Node> nodes = (labelName.equals(ASTERISK)) ? db.getAllNodes().iterator() : db.findNodes(label)) {
while (nodes.hasNext()) {
List<Node> batch = Util.take(nodes, BATCHSIZE);
futures.add(Util.inTxFuture(pool, db, () -> {
try {
for (Node node : batch) {
NodeKey key = keyFor(node, labelName, keys);
grouped.compute(key, (k, v) -> {
if (v == null)
v = new HashSet<>();
v.add(node);
return v;
});
virtualNodes.compute(key, (k, v) -> {
if (v == null) {
v = new VirtualNode(singleLabel, propertiesFor(node, keys), db);
}
Node vn = v;
if (!nodeAggNames.isEmpty()) {
aggregate(vn, nodeAggNames, nodeAggKeys.length > 0 ? node.getProperties(nodeAggKeys) : Collections.emptyMap());
}
return vn;
});
}
} catch (Exception e) {
log.debug("Error grouping nodes", e);
}
return null;
}));
Util.removeFinished(futures);
}
}
}
Util.waitForFutures(futures);
futures.clear();
Iterator<Map.Entry<NodeKey, Set<Node>>> entries = grouped.entrySet().iterator();
int size = 0;
List<Map.Entry<NodeKey, Set<Node>>> batch = new ArrayList<>();
while (entries.hasNext()) {
Map.Entry<NodeKey, Set<Node>> outerEntry = entries.next();
batch.add(outerEntry);
size += outerEntry.getValue().size();
if (size > BATCHSIZE || !entries.hasNext()) {
ArrayList<Map.Entry<NodeKey, Set<Node>>> submitted = new ArrayList<>(batch);
batch.clear();
size = 0;
futures.add(Util.inTxFuture(pool, db, () -> {
try {
for (Map.Entry<NodeKey, Set<Node>> entry : submitted) {
for (Node node : entry.getValue()) {
NodeKey startKey = entry.getKey();
Node v1 = virtualNodes.get(startKey);
for (Relationship rel : node.getRelationships(Direction.OUTGOING)) {
Node endNode = rel.getEndNode();
for (NodeKey endKey : keysFor(endNode, labels, keys)) {
Node v2 = virtualNodes.get(endKey);
if (v2 == null)
continue;
virtualRels.compute(new RelKey(startKey, endKey, rel), (rk, vRel) -> {
if (vRel == null)
vRel = v1.createRelationshipTo(v2, rel.getType());
if (!relAggNames.isEmpty()) {
aggregate(vRel, relAggNames, relAggKeys.length > 0 ? rel.getProperties(relAggKeys) : Collections.emptyMap());
}
return vRel;
});
}
}
}
}
} catch (Exception e) {
log.debug("Error grouping relationships", e);
}
return null;
}));
Util.removeFinished(futures);
}
}
Util.waitForFutures(futures);
return fixAggregates(virtualNodes.values()).stream().map(n -> new GraphResult(singletonList(n), fixAggregates(Iterables.asList(n.getRelationships()))));
}
use of apoc.Description in project neo4j-apoc-procedures by neo4j-contrib.
the class Bolt method load.
@Procedure()
@Description("apoc.bolt.load(url-or-key, statement, params, config) - access to other databases via bolt for read")
public Stream<RowResult> load(@Name("url") String url, @Name("statement") String statement, @Name(value = "params", defaultValue = "{}") Map<String, Object> params, @Name(value = "config", defaultValue = "{}") Map<String, Object> config) throws URISyntaxException {
if (params == null)
params = Collections.emptyMap();
if (config == null)
config = Collections.emptyMap();
boolean virtual = (boolean) config.getOrDefault("virtual", false);
boolean addStatistics = (boolean) config.getOrDefault("statistics", false);
boolean readOnly = (boolean) config.getOrDefault("readOnly", true);
Config driverConfig = toDriverConfig(config.getOrDefault("driverConfig", map()));
UriResolver uri = new UriResolver(url, "bolt");
uri.initialize();
try (Driver driver = GraphDatabase.driver(uri.getConfiguredUri(), uri.getToken(), driverConfig);
Session session = driver.session()) {
if (addStatistics)
return Stream.of(new RowResult(toMap(runStatement(statement, session, params, readOnly).summary().counters())));
else
return getRowResultStream(virtual, session, params, statement, readOnly);
} catch (Exception e) {
throw new RuntimeException("It's not possible to create a connection due to: " + e.getMessage());
}
}
use of apoc.Description in project neo4j-apoc-procedures by neo4j-contrib.
the class Cluster method graph.
@Procedure
@Description("apoc.cluster.graph - visually displays the servers participating in the Causal Cluster, their " + "roles, and which server in the cluster you are connected to.")
public Stream<GraphResult> graph() {
Result execute = db.execute("CALL dbms.cluster.overview()");
List<Node> servers = new LinkedList<>();
List<Relationship> relationships = new LinkedList<>();
while (execute.hasNext()) {
Map<String, Object> next = execute.next();
String role = (String) next.get("role");
String id = (String) next.get("id");
Label roleLabel = Label.label(role);
String[] addresses = ((List<String>) next.get("addresses")).toArray(new String[0]);
Map<String, Object> properties = new HashMap<>();
properties.put("name", shortName.get(role));
properties.put("title", role);
properties.put(boltAddressKey, addresses[0]);
properties.put("http_address", addresses[1]);
properties.put("cluster_id", id);
Node server = new VirtualNode(new Label[] { roleLabel }, properties, db);
servers.add(server);
}
Optional<Node> leaderNode = getLeaderNode(servers);
if (leaderNode.isPresent()) {
for (Node server : servers) {
if (server.hasLabel(Label.label("FOLLOWER"))) {
VirtualRelationship follows = new VirtualRelationship(server, leaderNode.get(), RelationshipType.withName("FOLLOWS"));
relationships.add(follows);
}
}
}
VirtualNode client = new VirtualNode(new Label[] { Label.label("CLIENT") }, singletonMap("name", "Client"), db);
Optional<Relationship> clientConnection = determineClientConnection(servers, client);
if (clientConnection.isPresent()) {
servers.add(client);
relationships.add(clientConnection.get());
}
GraphResult graphResult = new GraphResult(servers, relationships);
return Stream.of(graphResult);
}
use of apoc.Description in project neo4j-apoc-procedures by neo4j-contrib.
the class ExportCSV method graph.
@Procedure
@Description("apoc.export.csv.graph(graph,file,config) - exports given graph object as csv to the provided file")
public Stream<ProgressInfo> graph(@Name("graph") Map<String, Object> graph, @Name("file") String fileName, @Name("config") Map<String, Object> config) throws Exception {
Collection<Node> nodes = (Collection<Node>) graph.get("nodes");
Collection<Relationship> rels = (Collection<Relationship>) graph.get("relationships");
String source = String.format("graph: nodes(%d), rels(%d)", nodes.size(), rels.size());
return exportCsv(fileName, source, new NodesAndRelsSubGraph(db, nodes, rels), config);
}
use of apoc.Description in project neo4j-apoc-procedures by neo4j-contrib.
the class ExportCSV method query.
@Procedure
@Description("apoc.export.csv.query(query,file,{config,...,params:{params}}) - exports results from the cypher statement as csv to the provided file")
public Stream<ProgressInfo> query(@Name("query") String query, @Name("file") String fileName, @Name("config") Map<String, Object> config) throws Exception {
Map<String, Object> params = config == null ? Collections.emptyMap() : (Map<String, Object>) config.getOrDefault("params", Collections.emptyMap());
Result result = db.execute(query, params);
String source = String.format("statement: cols(%d)", result.columns().size());
return exportCsv(fileName, source, result, config);
}
Aggregations