Fingerprinting { @UserFunction @Description("calculate a checksum (md5) over a the full graph. Be aware that this function does use in-memomry datastructures depending on the size of your graph.") public String fingerprintGraph(@Name(value = "propertyExcludes", defaultValue = "[]") List<String> excludedPropertyKeys) { FingerprintingConfig config = new FingerprintingConfig(Util.map("allNodesDisallowList", excludedPropertyKeys, "allRelsDisallowList", excludedPropertyKeys, "mapDisallowList", excludedPropertyKeys, "strategy", FingerprintingConfig.FingerprintStrategy.EAGER.toString())); return withMessageDigest(config, messageDigest -> { Map<Long, String> idToNodeHash = tx.getAllNodes().stream().collect(Collectors.toMap( Node::getId, node -> fingerprint(node, config), (aLong, aLong2) -> { throw new RuntimeException(); }, () -> new TreeMap<>() )); Map<String, Long> nodeHashToId = idToNodeHash.entrySet().stream().collect(Collectors.toMap( Map.Entry::getValue, Map.Entry::getKey, (o, o2) -> { throw new RuntimeException(); }, () -> new TreeMap<>() )); nodeHashToId.entrySet().stream().forEach(entry -> { messageDigest.update(entry.getKey().getBytes()); Node node = tx.getNodeById(entry.getValue()); List<EndNodeRelationshipHashTuple> endNodeRelationshipHashTuples = StreamSupport.stream(node.getRelationships(Direction.OUTGOING).spliterator(), false) .map(relationship -> { String endNodeHash = idToNodeHash.get(relationship.getEndNodeId()); String relationshipHash = fingerprint(relationship, excludedPropertyKeys); return new EndNodeRelationshipHashTuple(endNodeHash, relationshipHash); }).collect(Collectors.toList()); endNodeRelationshipHashTuples.stream().sorted().forEach(endNodeRelationshipHashTuple -> { messageDigest.update(endNodeRelationshipHashTuple.getEndNodeHash().getBytes()); messageDigest.update(endNodeRelationshipHashTuple.getRelationshipHash().getBytes()); }); }); }); }  @UserFunction @Description("calculate a checksum (md5) over a node or a relationship. This deals gracefully with array properties. Two identical entities do share the same hash.") String fingerprint(@Name("some object") Object thing, @Name(value = "propertyExcludes", defaultValue = "[]") List<String> excludedPropertyKeys); @UserFunction @Description("calculate a checksum (md5) over a node or a relationship. This deals gracefully with array properties. Two identical entities do share the same hash.") String fingerprinting(@Name("some object") Object thing, @Name(value = "conf", defaultValue = "{}") Map<String, Object> conf); @UserFunction @Description("calculate a checksum (md5) over a the full graph. Be aware that this function does use in-memomry datastructures depending on the size of your graph.") String fingerprintGraph(@Name(value = "propertyExcludes", defaultValue = "[]") List<String> excludedPropertyKeys); @Context
    public Transaction tx; @Context
    public Log log; }
@Test public void fingerprintGraph() { compareGraph("CREATE (:Person{name:'ABC'})-[:KNOWS{since:12345}]->(:Person{name:'DEF'})", EMPTY_LIST, true); }