From 5cf89d3db485f8935d54b4e7d27484a21d9688a1 Mon Sep 17 00:00:00 2001 From: InverseFalcon Date: Sat, 8 Apr 2017 01:17:56 -0700 Subject: [PATCH] Prevented path expander termination filter from filtering below minLevel --- src/main/java/apoc/path/PathExplorer.java | 20 ++++++++++++-------- src/test/java/apoc/path/ExpandPathTest.java | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/main/java/apoc/path/PathExplorer.java b/src/main/java/apoc/path/PathExplorer.java index b29312b553..0dbee3aa30 100644 --- a/src/main/java/apoc/path/PathExplorer.java +++ b/src/main/java/apoc/path/PathExplorer.java @@ -234,7 +234,14 @@ public LabelEvaluator(String labelFilter, boolean filterStartNode, long limit, i @Override public Evaluation evaluate(Path path) { int depth = path.length(); - // if start node shouldn't be filtered + Node check = path.endNode(); + + // below minLevel always exclude; continue if blacklist and whitelist allow it + if (depth < minLevel) { + return labelExists(check, blacklistLabels) || !whitelistAllowed(check) ? EXCLUDE_AND_PRUNE : EXCLUDE_AND_CONTINUE; + } + + // if start node shouldn't be filtered, exclude/include based on if using termination/endnode filter or not if (depth == 0 && !filterStartNode) { return whitelistAllowedEvaluation; } @@ -244,10 +251,9 @@ public Evaluation evaluate(Path path) { return EXCLUDE_AND_PRUNE; } - Node check = path.endNode(); Evaluation result = labelExists(check, blacklistLabels) ? EXCLUDE_AND_PRUNE : - labelExists(check, terminationLabels) ? filterEndNode(check, depth, true) : - labelExists(check, endNodeLabels) ? filterEndNode(check, depth, false) : + labelExists(check, terminationLabels) ? filterEndNode(check, true) : + labelExists(check, endNodeLabels) ? filterEndNode(check, false) : whitelistAllowed(check) ? whitelistAllowedEvaluation : EXCLUDE_AND_PRUNE; return result; @@ -270,10 +276,8 @@ private boolean whitelistAllowed(Node node) { return whitelistLabels.isEmpty() || labelExists(node, whitelistLabels); } - private Evaluation filterEndNode(Node node, int depth, boolean isTerminationFilter) { - if (depth >= minLevel) { - resultCount++; - } + private Evaluation filterEndNode(Node node, boolean isTerminationFilter) { + resultCount++; return isTerminationFilter || !whitelistAllowed(node) ? INCLUDE_AND_PRUNE : INCLUDE_AND_CONTINUE; } } diff --git a/src/test/java/apoc/path/ExpandPathTest.java b/src/test/java/apoc/path/ExpandPathTest.java index f3d4c2a3dc..6784945800 100644 --- a/src/test/java/apoc/path/ExpandPathTest.java +++ b/src/test/java/apoc/path/ExpandPathTest.java @@ -247,4 +247,20 @@ public void testLimitPlaysNiceWithMinLevel() { assertEquals("Clint Eastwood", path.endNode().getProperty("name")); }); } + + @Test + public void testTerminationFilterDoesNotPruneBelowMinLevel() { + db.execute("MATCH (c:Person) WHERE c.name in ['Clint Eastwood', 'Gene Hackman'] SET c:Western"); + + TestUtil.testResult(db, + "MATCH (k:Person {name:'Keanu Reeves'}) " + + "CALL apoc.path.expandConfig(k, {relationshipFilter:'ACTED_IN|PRODUCED|DIRECTED', labelFilter:'/Western', uniqueness: 'NODE_GLOBAL', minLevel:3}) yield path " + + "return path", + result -> { + List> maps = Iterators.asList(result); + assertEquals(1, maps.size()); + Path path = (Path) maps.get(0).get("path"); + assertEquals("Clint Eastwood", path.endNode().getProperty("name")); + }); + } }