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 | | any type | OUTGOING +| < | any type | INCOMING |=== ==== Label Filter diff --git a/docs/overview.adoc b/docs/overview.adoc index ae3a1b2eb4..0cc58f9664 100644 --- a/docs/overview.adoc +++ b/docs/overview.adoc @@ -1038,6 +1038,8 @@ Syntax: `[<]RELATIONSHIP_TYPE1[>]|[<]RELATIONSHIP_TYPE2[>]|...` | LIKES> | LIKES | OUTGOING | | 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 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 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> maps = Iterators.asList(result); + assertEquals(1, maps.size()); + List titles = (List) 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> 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 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> maps = Iterators.asList(result); + assertEquals(1, maps.size()); + List names = (List) 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, { + List 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 names = (List) row.get("names"); + assertEquals(13l, names.size()); + assertTrue(names.containsAll(expectedNames)); + }); + } }