diff --git a/docs/expand.adoc b/docs/expand.adoc index ddf4524ec7..be90ed369e 100644 --- a/docs/expand.adoc +++ b/docs/expand.adoc @@ -31,6 +31,8 @@ Syntax: `[<]RELATIONSHIP_TYPE1[>]|[<]RELATIONSHIP_TYPE2[>]|...` | LIKES> | LIKES | OUTGOING | <FOLLOWS | FOLLOWS | INCOMING | KNOWS | KNOWS | BOTH +| > | any type | OUTGOING +| < | any type | INCOMING |=== ==== Label Filter diff --git a/docs/overview.adoc b/docs/overview.adoc index e2b874b21a..48702b3292 100644 --- a/docs/overview.adoc +++ b/docs/overview.adoc @@ -1034,6 +1034,8 @@ Syntax: `[<]RELATIONSHIP_TYPE1[>]|[<]RELATIONSHIP_TYPE2[>]|...` | LIKES> | LIKES | OUTGOING | <FOLLOWS | FOLLOWS | INCOMING | KNOWS | KNOWS | BOTH +| > | any type | OUTGOING +| < | any type | INCOMING |=== === Label Filter diff --git a/src/main/java/apoc/path/RelationshipSequenceExpander.java b/src/main/java/apoc/path/RelationshipSequenceExpander.java index be2d72a753..59168fbe73 100644 --- a/src/main/java/apoc/path/RelationshipSequenceExpander.java +++ b/src/main/java/apoc/path/RelationshipSequenceExpander.java @@ -92,8 +92,13 @@ protected Iterator<Relationship> createNestedIterator( { RelationshipType type = entry.first(); Direction dir = entry.other(); - return ( ( dir == Direction.BOTH ) ? node.getRelationships( type ) : - node.getRelationships( type, dir ) ).iterator(); + if (type != null) { + return ((dir == Direction.BOTH) ? node.getRelationships(type) : + node.getRelationships(type, dir)).iterator(); + } else { + return ((dir == Direction.BOTH) ? node.getRelationships() : + node.getRelationships(dir)).iterator(); + } } }); } diff --git a/src/test/java/apoc/path/ExpandPathTest.java b/src/test/java/apoc/path/ExpandPathTest.java index 5c6804d095..d5a7e76377 100644 --- a/src/test/java/apoc/path/ExpandPathTest.java +++ b/src/test/java/apoc/path/ExpandPathTest.java @@ -14,6 +14,7 @@ import apoc.util.TestUtil; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -325,4 +326,34 @@ public void testCompoundLabelWorksInBlacklist() { assertEquals("Gene Hackman", node.getProperty("name")); }); } + + @Test + public void testRelationshipFilterWorksWithoutTypeOutgoing() { + TestUtil.testResult(db, + "MATCH (k:Person {name:'Keanu Reeves'}) " + + "CALL apoc.path.subgraphNodes(k, {relationshipFilter:'>', labelFilter:'>Movie', uniqueness: 'NODE_GLOBAL'}) yield node " + + "return collect(node.title) as titles", + result -> { + + List<String> expectedTitles = new ArrayList<>(Arrays.asList("Something's Gotta Give", "Johnny Mnemonic", "The Replacements", "The Devil's Advocate", "The Matrix Revolutions", "The Matrix Reloaded", "The Matrix")); + List<Map<String, Object>> maps = Iterators.asList(result); + assertEquals(1, maps.size()); + List<String> titles = (List<String>) maps.get(0).get("titles"); + assertEquals(7, titles.size()); + assertTrue(titles.containsAll(expectedTitles)); + }); + } + + @Test + public void testRelationshipFilterWorksWithoutTypeIncoming() { + TestUtil.testResult(db, + "MATCH (k:Person {name:'Keanu Reeves'}) " + + "CALL apoc.path.subgraphNodes(k, {relationshipFilter:'<', labelFilter:'>BigBrother', uniqueness: 'NODE_GLOBAL'}) yield node " + + "return node", + result -> { + + List<Map<String, Object>> maps = Iterators.asList(result); + assertEquals(1, maps.size()); + }); + } } diff --git a/src/test/java/apoc/path/RelSequenceTest.java b/src/test/java/apoc/path/RelSequenceTest.java index ba7268341d..de1da04d2b 100644 --- a/src/test/java/apoc/path/RelSequenceTest.java +++ b/src/test/java/apoc/path/RelSequenceTest.java @@ -7,11 +7,13 @@ import org.junit.Test; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Transaction; +import org.neo4j.helpers.collection.Iterators; import org.neo4j.test.TestGraphDatabaseFactory; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -84,4 +86,20 @@ public void testRelSequenceWhenNotBeginningAtStart() throws Throwable { assertTrue(names.containsAll(expectedNames)); }); } + + @Test + public void testRelationshipFilterWorksWithoutTypeWithRelSequence() { + TestUtil.testResult(db, + "MATCH (k:Person {name:'Keanu Reeves'}) " + + "CALL apoc.path.subgraphNodes(k, {relationshipFilter:'>,<', labelFilter:'/Person'}) yield node " + + "return collect(node.name) as names", + result -> { + List<String> expectedNames = new ArrayList<>(Arrays.asList("Nancy Meyers", "Jack Nicholson", "Diane Keaton", "Dina Meyer", "Ice-T", "Takeshi Kitano", "Robert Longo", "Jessica Thompson", "Angela Scope", "James Thompson", "Brooke Langton", "Gene Hackman", "Orlando Jones", "Howard Deutch", "Al Pacino", "Taylor Hackford", "Charlize Theron", "Lana Wachowski", "Joel Silver", "Hugo Weaving", "Andy Wachowski", "Carrie-Anne Moss", "Laurence Fishburne", "Emil Eifrem")); + List<Map<String, Object>> maps = Iterators.asList(result); + assertEquals(1, maps.size()); + List<String> names = (List<String>) maps.get(0).get("names"); + assertEquals(24, names.size()); + assertTrue(names.containsAll(expectedNames)); + }); + } } diff --git a/src/test/java/apoc/path/SequenceTest.java b/src/test/java/apoc/path/SequenceTest.java index 84d9560883..03327bb877 100644 --- a/src/test/java/apoc/path/SequenceTest.java +++ b/src/test/java/apoc/path/SequenceTest.java @@ -7,11 +7,13 @@ import org.junit.Test; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Transaction; +import org.neo4j.helpers.collection.Iterators; import org.neo4j.test.TestGraphDatabaseFactory; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -106,4 +108,15 @@ public void testExpandWithSequenceIgnoresLabelFilter() throws Throwable { assertTrue(names.containsAll(expectedNames)); }); } + + @Test + public void testRelationshipFilterWorksWithoutTypeWithFullSequence() { + String query = "MATCH (t:Person {name: 'Tom Hanks'}) CALL apoc.path.expandConfig(t,{sequence:'>Person, >, Movie, <DIRECTED'}) yield path with distinct last(nodes(path)) as node return collect(node.name) as names"; + TestUtil.testCall(db, query, (row) -> { + List<String> expectedNames = new ArrayList<>(Arrays.asList("Mike Nichols", "Robert Zemeckis", "Penny Marshall", "Ron Howard", "Frank Darabont", "Andy Wachowski", "Lana Wachowski", "Tom Tykwer", "Tom Hanks", "John Patrick Stanley", "Nora Ephron", "James Marshall", "Rob Reiner")); + List<String> names = (List<String>) row.get("names"); + assertEquals(13l, names.size()); + assertTrue(names.containsAll(expectedNames)); + }); + } }