cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Best way to find node neighborhood?

cnhx27
Node Link

Hello,
I'm starting with Neo4J. For a given node I want to list Outgoing & Incoming relationships.
I do this :

// List Outgoing & Incoming relations for a node
// Outgoing
MATCH (s)-[r]->(t)
WHERE s.name = 'f4b1'
RETURN t.name , 'Out' as `relations`
UNION ALL
// Incoming
MATCH (t)<-[r]-(s)
WHERE t.name = 'f4b1'
RETURN t.name , 'In' as `relations`

Is this the best way?

1 ACCEPTED SOLUTION

You can use pattern comprehension for this:

MATCH (s) // you should really use labels here, and create an index to support fast lookup by property
WHERE s.name = 'f4b1'
RETURN [(s)<--(t) | t.name] as In, [(s)-->(t) | t.name] as Out

View solution in original post

6 REPLIES 6

krisgeus
Node Clone

Example based on the movies dataset without the need for a JOIN:

MATCH (p:Person {name: "Jessica Thompson"})-[r]-(o)
RETURN p.name
              , p = endNode(r) as isIncoming
              , type(r) as relationType
              , coalesce(o.name, o.title) as other

cnhx27
Node Link

Thank you so much for your help.

Do you think is it possible to have an inRel array with the inComing node IDs and an outRel array with the outgoing node IDs`?

You can use pattern comprehension for this:

MATCH (s) // you should really use labels here, and create an index to support fast lookup by property
WHERE s.name = 'f4b1'
RETURN [(s)<--(t) | t.name] as In, [(s)-->(t) | t.name] as Out

If you have multiple relationships, you can use DISTINCT.

MATCH (t_in)-->(s)-->(t_out)
WHERE s.name = 'f4b1'
RETURN collect(DISTINCT(t_in.name)) as In,
       collect(DISTINCT(t_out.name)) as Out;

This is the cypher for creation.

CREATE (n:S{name:'f4b1'}),
       (in1:In{name:'data_in_1'})-[:REL]->(n)-[:REL]->(:Out{name:'data_out_1'}),
       (:In{name:'data_in_2'})-[:REL]->(n)-[:REL]->(:Out{name:'data_out_2'}),
       (:In{name:'data_in_3'})-[:REL]->(n)-[:REL]->(:Out{name:'data_out_3'}),
       (:In{name:'data_in_4'})-[:REL]->(n),
       (n)-[:REL]->(out5:Out{name:'data_out_5'}),
       (n)-[:REL]->(:Out{name:'data_out_6'}),
       (in1)-[:REL]->(n),
       (n)-[:REL2]->(out5);

'data_in_1' and 'data_out_5' are displayed only one each.

2X_d_d33780aa678fd475592f8ba8f850efd410358a43.jpeg

cnhx27
Node Link

Thank you all so much. Very informative.

@andrew.bowman:
About your comment: you should really use labels here, and create an index to support fast lookup by property I do this :

MATCH (s:User)
WHERE s.name = 'f4b1'
RETURN [(s)<--(t) | t.name] as In, [(s)-->(t) | t.name] as Out

name is unique per user, I just create an constraint like this:
CREATE CONSTRAINT ON (n:User) ASSERT n.name IS UNIQUE

If name isn't unique per user, J just create a plain index instead:
CREATE INDEX ON :User(name)

Is that correct?

Yep, looks good.

You can always confirm if an index is being used or not by running an EXPLAIN of the query, it will show you how the starting nodes are looked up.