Meta { private Stream<GraphResult> metaGraph(Collection<String> labelNames, Collection<String> relTypeNames, boolean removeMissing, MetaConfig metaConfig) { Read read = kernelTx.dataRead(); TokenRead tokenRead = kernelTx.tokenRead(); Map<String, Integer> labels = labelsInUse(tokenRead, labelNames); Map<String, Integer> relTypes = relTypesInUse(tokenRead, relTypeNames); Map<String, Node> vNodes = new TreeMap<>(); Map<Pattern, Relationship> vRels = new HashMap<>(relTypes.size() * 2); labels.forEach((labelName, id) -> { long count = read.countsForNodeWithoutTxState(id); if (count > 0) { mergeMetaNode(Label.label(labelName), vNodes, count); } }); relTypes.forEach((typeName, typeId) -> { long global = read.countsForRelationshipWithoutTxState(ANY_LABEL, typeId, ANY_LABEL); labels.forEach((labelNameA, labelIdA) -> { long relCountOut = read.countsForRelationshipWithoutTxState(labelIdA, typeId, ANY_LABEL); if (relCountOut > 0) { labels.forEach((labelNameB, labelIdB) -> { long relCountIn = read.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, metaConfig); GraphResult graphResult = new GraphResult(new ArrayList<>(vNodes.values()), new ArrayList<>(vRels.values())); return Stream.of(graphResult); }  @Deprecated @UserFunction @Description("apoc.meta.type(value) - type name of a value (INTEGER,FLOAT,STRING,BOOLEAN,RELATIONSHIP,NODE,PATH,NULL,UNKNOWN,MAP,LIST)") String type(@Name("value") Object value); @Deprecated @UserFunction @Description("apoc.meta.typeName(value) - type name of a value (INTEGER,FLOAT,STRING,BOOLEAN,RELATIONSHIP,NODE,PATH,NULL,UNKNOWN,MAP,LIST)") String typeName(@Name("value") Object value); @Deprecated @UserFunction @Description("apoc.meta.types(node-relationship-map) - returns a map of keys to types") Map<String,Object> types(@Name("properties") Object target); @Deprecated @UserFunction @Description("apoc.meta.isType(value,type) - returns a row if type name matches none if not (INTEGER,FLOAT,STRING,BOOLEAN,RELATIONSHIP,NODE,PATH,NULL,UNKNOWN,MAP,LIST)") boolean isType(@Name("value") Object value, @Name("type") String type); @UserFunction("apoc.meta.cypher.isType") @Description("apoc.meta.cypher.isType(value,type) - returns a row if type name matches none if not (INTEGER,FLOAT,STRING,BOOLEAN,RELATIONSHIP,NODE,PATH,NULL,MAP,LIST OF <TYPE>,POINT,DATE,DATE_TIME,LOCAL_TIME,LOCAL_DATE_TIME,TIME,DURATION)") boolean isTypeCypher(@Name("value") Object value, @Name("type") String type); @UserFunction("apoc.meta.cypher.type") @Description("apoc.meta.cypher.type(value) - type name of a value (INTEGER,FLOAT,STRING,BOOLEAN,RELATIONSHIP,NODE,PATH,NULL,MAP,LIST OF <TYPE>,POINT,DATE,DATE_TIME,LOCAL_TIME,LOCAL_DATE_TIME,TIME,DURATION)") String typeCypher(@Name("value") Object value); @UserFunction("apoc.meta.cypher.types") @Description("apoc.meta.cypher.types(node-relationship-map) - returns a map of keys to types") Map<String,Object> typesCypher(@Name("properties") Object target); @Procedure @Description("apoc.meta.stats yield labelCount, relTypeCount, propertyKeyCount, nodeCount, relCount, labels, relTypes, stats | returns the information stored in the transactional database statistics") Stream<MetaStats> stats(); @Procedure @Description("apoc.meta.data({config}) - examines a subset of the graph to provide a tabular meta information") Stream<MetaResult> data(@Name(value = "config",defaultValue = "{}") Map<String,Object> config); @Procedure @Description("apoc.meta.schema({config}) - examines a subset of the graph to provide a map-like meta information") Stream<MapResult> schema(@Name(value = "config",defaultValue = "{}") Map<String,Object> config); @Procedure @Description("apoc.meta.nodeTypeProperties()") Stream<Tables4LabelsProfile.NodeTypePropertiesEntry> nodeTypeProperties(@Name(value = "config",defaultValue = "{}") Map<String,Object> config); @Procedure @Description("apoc.meta.relTypeProperties()") Stream<Tables4LabelsProfile.RelTypePropertiesEntry> relTypeProperties(@Name(value = "config",defaultValue = "{}") Map<String,Object> config); long getSampleForLabelCount(long labelCount, long sample); void sample(GraphDatabaseService db, Sampler sampler, int sampleSize); @Procedure @Description("apoc.meta.graph - examines the full graph to create the meta-graph") Stream<GraphResult> graph(@Name(value = "config",defaultValue = "{}") Map<String,Object> config); @Procedure @Description("apoc.meta.graphSample() - examines the database statistics to build the meta graph, very fast, might report extra relationships") Stream<GraphResult> graphSample(@Name(value = "config",defaultValue = "{}") Map<String,Object> config); @Procedure @Description("apoc.meta.subGraph({labels:[labels],rels:[rel-types], excludes:[labels,rel-types]}) - examines a sample sub graph to create the meta-graph") Stream<GraphResult> subGraph(@Name("config") Map<String,Object> config ); @Context
    public Transaction tx; @Context
    public GraphDatabaseService db; @Context
    public KernelTransaction kernelTx; @Context
    public Transaction transaction; @Context public Log log; }
@Test public void testMetaGraph() throws Exception { db.executeTransactionally("CREATE (a:Actor)-[:ACTED_IN]->(m1:Movie),(a)-[:ACTED_IN]->(m2:Movie)"); TestUtil.testCall(db, "CALL apoc.meta.graph()", (row) -> { List<Node> nodes = (List<Node>) row.get("nodes"); Node n1 = nodes.get(0); assertEquals(true, n1.hasLabel(Label.label("Actor"))); assertEquals(1L, n1.getProperty("count")); assertEquals("Actor", n1.getProperty("name")); Node n2 = nodes.get(1); assertEquals(true, n2.hasLabel(Label.label("Movie"))); assertEquals("Movie", n2.getProperty("name")); assertEquals(2L, n2.getProperty("count")); List<Relationship> rels = (List<Relationship>) row.get("relationships"); Relationship rel = rels.iterator().next(); assertEquals("ACTED_IN", rel.getType().name()); assertEquals(2L, rel.getProperty("count")); }); }