use of apoc.result.GraphResult 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.result.GraphResult 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.result.GraphResult in project neo4j-apoc-procedures by neo4j-contrib.
the class Meta method metaGraph.
private Stream<GraphResult> metaGraph(Collection<String> labelNames, Collection<String> relTypeNames, boolean removeMissing) {
try (Statement stmt = kernelTx.acquireStatement()) {
ReadOperations ops = stmt.readOperations();
Map<String, Integer> labels = labelsInUse(ops, labelNames);
Map<String, Integer> relTypes = relTypesInUse(ops, relTypeNames);
Map<String, Node> vNodes = new TreeMap<>();
Map<Pattern, Relationship> vRels = new HashMap<>(relTypes.size() * 2);
labels.forEach((labelName, id) -> {
long count = ops.countsForNodeWithoutTxState(id);
if (count > 0) {
mergeMetaNode(Label.label(labelName), vNodes, count);
}
});
relTypes.forEach((typeName, typeId) -> {
long global = ops.countsForRelationshipWithoutTxState(ANY_LABEL, typeId, ANY_LABEL);
labels.forEach((labelNameA, labelIdA) -> {
long relCountOut = ops.countsForRelationshipWithoutTxState(labelIdA, typeId, ANY_LABEL);
if (relCountOut > 0) {
labels.forEach((labelNameB, labelIdB) -> {
long relCountIn = ops.countsForRelationshipWithoutTxState(ANY_LABEL, typeId, labelIdB);
if (relCountIn > 0) {
Node nodeA = vNodes.get(labelNameA);
Node nodeB = vNodes.get(labelNameB);
Relationship vRel = new VirtualRelationship(nodeA, nodeB, RelationshipType.withName(typeName)).withProperties(map("type", typeName, "out", relCountOut, "in", relCountIn, "count", global));
vRels.put(Pattern.of(labelNameA, typeName, labelNameB), vRel);
}
});
}
});
});
if (removeMissing)
filterNonExistingRelationships(vRels);
GraphResult graphResult = new GraphResult(new ArrayList<>(vNodes.values()), new ArrayList<>(vRels.values()));
return Stream.of(graphResult);
}
}
use of apoc.result.GraphResult in project neo4j-apoc-procedures by neo4j-contrib.
the class PathExplorer method subgraphAll.
@Procedure("apoc.path.subgraphAll")
@Description("apoc.path.subgraphAll(startNode <id>|Node|list, {maxLevel,relationshipFilter,labelFilter,bfs:true, filterStartNode:false, limit:-1, endNodes:[], terminatorNodes:[], sequence, beginSequenceAtStart:true}) yield nodes, relationships - expand the subgraph reachable from start node following relationships to max-level adhering to the label filters, and also return all relationships within the subgraph")
public Stream<GraphResult> subgraphAll(@Name("start") Object start, @Name("config") Map<String, Object> config) throws Exception {
Map<String, Object> configMap = new HashMap<>(config);
// not needed, will return empty collections anyway if no results
configMap.remove("optional");
configMap.put("uniqueness", "NODE_GLOBAL");
if (config.containsKey("minLevel")) {
throw new IllegalArgumentException("minLevel not supported in subgraphAll");
}
List<Node> subgraphNodes = expandConfigPrivate(start, configMap).map(Path::endNode).collect(Collectors.toList());
List<Relationship> subgraphRels = Cover.coverNodes(subgraphNodes).collect(Collectors.toList());
return Stream.of(new GraphResult(subgraphNodes, subgraphRels));
}
Aggregations