What I'm trying to do is simply start at a node and search for all connected nodes that are a certain label. However I don't want to return the start node. How would I do this?
Example:
...<-[:parent]<-anode<-[created]-user-[created]->anode-[:parent]->anode-....->nodes...
What I would like to do is start at the user node and return all relationships but excluding the user node.
This will return you a list of all nodes connected via created relationships of a distance of up to 10.
MATCH user-[:created*1..10]->(anode:CertainLabel)
RETURN DISTINCT anode
Depending on your graph, you may be able to get rid of the 10, but if it's large and complex removing the max value could cause your query to run very slowly
This is along the lines of what I was looking for.
START u = node(26)
MATCH (u)-[rels*1..10]->(node) unwind rels as r
RETURN DISTINCT id(startNode(r)),endNode(r)
Related
I have a huge (non cyclic) graph and want to find all nodes reachable by relation X from a given node. However, I do not want to cross a node having a certain attribute {attr:'donotcross'} as this represents a choke point I do not want to cross (i.e. this is the only node leading to an adjacent subgraph).
Currently I do breadth first search myself using a trivial Cypher query to isolate neighboring nodes and python, stopping the recursion as soon as I reach that specific node. This, however, is really slow and I think that using pure Cypher to isolate those nodes could be faster.
What does the Cypher query look like returning all connected nodes via X but not traversing a node with property attr:'donotcross'?
My intuition would be
MATCH (n)-[:X*]->(inter)-[:X*]->(m) WHERE NOT inter.attr = 'donotcross' RETURN m
With n being the start node. However, this does not work as this pattern can match a path with a forbidden node if there are more than the forbidden node in between the start and target node.
Using Cypher alone, you can use the following approach:
MATCH path = (n)-[:X*]->(m) // best to use a label!
WHERE none(node in nodes(path) WHERE inter.attr = 'donotcross')
RETURN DISTINCT m
Keep in mind you should at least be using labels for your starting node n, if you aren't able to look them up by an indexed property for a specific label.
Also, if there are relatively few of these donotcross nodes, and if there is an index on the label of these nodes on attr, then it may be faster to first match on these nodes, collect them, then filter based on that:
MATCH (x) // best to use a label and index lookup!
WHERE x.attr = 'donotcross'
WITH collect(x) as excluded
MATCH path = (n)-[:X*]->(m) // best to use a label!
WHERE none(node in nodes(path) WHERE node in excluded)
RETURN DISTINCT m
I'm sure this is an easy cypher query, but I'm relatively new to cypher, so apologies ahead of time, but I can't find a previously asked question.
If I have a bunch of nodes connected like this:
(:Start)-[:NEXT]->(step1)-[:NEXT]->(step2)-[:NEXT]->(step3)-[:NEXT]->etc.
And I want to return all the nodes in this group, I can write this:
match (s:Start)-[:NEXT*]->(steps)
return s, steps
But what if I want to order them by their distance from the starting node? Is there a characteristic I an apply order by to or is it more complicated than that?
Thanks
You can enforce the ordering by introducing a variable on the collection of :NEXT relationships, and ordering by their size (how many :NEXTs to get to the node).
MATCH (s:Start)-[rels:NEXT*]->(steps)
RETURN s, steps
ORDER BY SIZE(rels)
Nodes of paths are returned in their sequenced order, so you can use the nodes collection as starting point :
MATCH (s:Start)-[rels:NEXT*]->(steps)
UNWIND range(1, size(nodes(p))-1) AS i
RETURN nodes(p)[i] as node, i
ORDER BY i
Example of this query against the console example : http://console.neo4j.org/r/7nzgov
How can we add a relationship to the query.
Say A-[C01]-B-[C02]-D and A-[C01]-B-[C03]-E
C01 C02 C03 are relationship codes I want to get output
B E
because I want only nodes that can be reached unbroken by C01 or C03
How can I get this result in Cypher?
You may want to clarify, what you're asking for seems like a very simple case of matching. You may want to provide some more info, such as node labels and how you're matching to your start nodes, since without these we have to make things up for example code.
MATCH (a:Thing)
WHERE a.ID = 123
WITH a
MATCH (a)-[:C01|C03*]->(b:Thing)
RETURN b
The key here is specifying multiple relationship types to traverse, using * for multiplicity, so it will match on all nodes that can be reached by any chain of those relationships.
In a graph where the following nodes
A,B,C,D
have a relationship with each nodes successor
(A->B)
and
(B->C)
etc.
How do i make a query that starts with A and gives me all nodes (and relationships) from that and outwards.
I do not know the end node (C).
All i know is to start from A, and traverse the whole connected graph (with conditions on relationship and node type)
I think, you need to use this pattern:
(n)-[*]->(m) - variable length path of any number of relationships from n to m. (see Refcard)
A sample query would be:
MATCH path = (a:A)-[*]->()
RETURN path
Have also a look at the path functions in the refcard to expand your cypher query (I don't know what exact conditions you'll need to apply).
To get all the nodes / relationships starting at a node:
MATCH (a:A {id: "id"})-[r*]-(b)
RETURN a, r, b
This will return all the graphs originating with node A / Label A where id = "id".
One caveat - if this graph is large the query will take a long time to run.
My graph looks like this
medium-[:firstChapter]->chapter1-[:nextChapter]->chapter2_to_N
there is only one node connected via :firstChapter and then several nodes may follow, connected via :nextChapter
I tried to match all nodes that are either connected via relationship :firstChapter to medium or connected via :nextChapter from one chapter to another
The query I tried looks like this
start n=node(543) match n-[:firstChapter|nextChapter*]->m return m;
node(543) is the node medium.
Surprisingly, this query returns all nodes in the path, even though the nodes are not connected to n (=medium node)
If I leave out the * sign after nextChapter, only the first node with the :firstChapter relationship is returned (chapter1), which seems to be correct.
start n=node(543) match n-[:firstChapter|nextChapter*]->m return m;
Why does the query above return nodes not connected to n? As far as I understand it, the * sign usually returns nodes that are an unlimited number of relationships away, right?
What is the best way to match all nodes of a path (only once) that are either connected via :firstChapter or :nextChapter to a start node? In this case all chapters
The query above serves that purpose, but I don't think the output is correct...
EDIT:
Added a diagramm to clarify.
As you can see, the first chapter may only be reached via :firstChapter,
So it is still unclear, why the query above returns ALL chapter nodes
Try doing match p=n-[:firstChapter|nextChapter*]->m to see what p is. Hopefully that provides some insight about how they are connected.
What you might be looking for in the end is:
start n=node(543)
match n-[:firstChapter|nextChapter*]->m
return collect(distinct m);
To get a collection of distinct chapter nodes that follow n.
update
Here's another one--didn't actually test it but it might get you closer to what you want:
start n=node(543)
match n-[:firstChapter]->f-[:nextChapter*]-m
return f + collect(distinct m);
Using the * operator, the query looks for all relationships along the line for both relationship types, :firstChapter and :nextChapter (not just :nextChapter). Your chapter data for node(543) likely contains some relationships to chapter nodes not in the 543 chain and the query is returning them.
Consider adding an extra relationship using type :nextChapter to connect the start node to the first chapter, and check the relationships that exist on your chapters.
Then run:
start n=node(543)
match n-[:nextChapter*]->m
return m;
and see if you still get extra results. If so, you could run the following, bumping up n each time until you find the node that has the extra relationship(s) - (though I'm sure there are other ways!)
start n=node(543)
match n-[:nextChapter*1..n]->m
return m;