neo4j cypher multi relationship between nodes - neo4j

for example:
a-[r]->b, there are multi r between the two nodes, each r.userId is unique.
(eg: a-[r:R {userId:"user1"}]->b, (a-[r:R{userId:"user2"}]->b,
and the same for a-[r]->c
And the situation is a-[r]->b has a relationship: r.userId = amdin, but a-[r]->c doesn't have this relationship.
how can i only return c.
i try to create cypher:
"MATCH (a:SomeLabel)-[r:SomeR]->(any:SomeLabel) "
"WHERE id(a)=0 AND r.userId <> \"admin\" "
"RETURN any";
but this will also return b ,because a->b has other relationship: r.userId=xxxx
how can i write the cypher to return nodes not inculde user.Id="admin"......
If you not clearly understand what i say,please let me know....i need your help for this case..thanks
I draw a picture below, multi relationship named sr but with different properties (userId is unique),
and i want to find all nodes that related to node A, but not contains sr {userId:admin}, i add a red underline there. So as in the picture, node B has the relationship sr {userId:admin}, so i only want to return node C, no node B

For showing simple representations of graph problems, graphgists are really helpful as people can explore the data.
I've created one based on your description: http://gist.neo4j.org/?94ef056e41153b116e4f
To your problem, you can collect all usernames involved in the relationships per pair of nodes and filter based on those:
MATCH (a { name:'A' })-[r:sr]->b
WITH a,b, collect(r.name) AS usernames
WHERE NOT 'admin' IN usernames
RETURN a, b

Your question is pretty unclear. My interpretation is that you want to find nodes c that are not connected to a node a with a relationship of type R.
You basically want to do a negative match aka search for a pattern that does not exist. Negative patterns can be retrieved using a where not:
MATCH (a:SomeLabel), (c:SomeLabel)
WHERE ID(a)=0 AND NOT (a)-[:R]->(c)
RETURN c
This returns a list of all SomeLabel nodes not being connected to a.
See http://docs.neo4j.org/chunked/stable/query-where.html#query-where-patterns in the reference manual.

Related

Cypher - Delete node with given property and reconnect graph

I have a graph consisting of paths.
I need to delete all nodes, that have a property:
linksTo:'javascript'
After deleting i have to reconnect the paths. This means i need to create a new relationship for each gap. This relationship has a property named deltaTime that holds some integer value. This value (deltaTime) should be the sum of all deltaTime-properties of the deleted relationships of this path. Please look at the following picture for better understanding.
I don't know how to detect multiple "bad" nodes in a row, with a variable row-length.
It would help if you could provide the labels involved in your graph, as well as the relationship types you're using.
Assuming all these paths are chains (only single relationships connecting each node), something like this should work for you:
// first, add a label on all the nodes we plan on deleting
// it helps if they already have the same label especially if linksTo property is indexed.
MATCH (n{linksTo:'javascript'})
SET n:ToDelete
With the appropriate nodes labeled, we'll find the segments of nodes to delete, the surrounding nodes that need to be connected, and create the new relationship. We ensure a and b are start and end nodes of the chain by ensuring there are no :ToDelete nodes linking to a, or from b.
MATCH (a:ToDelete)
WHERE NOT (:ToDelete)-->(a)
AND ()-->(a)
MATCH p = (a)-[rel*0..]->(b:ToDelete)
WHERE ALL(node in nodes(p) WHERE node:ToDelete)
AND NOT (b)-->(:ToDelete)
AND (b)-->()
WITH a, b, REDUCE(s = 0, r IN rel | s + r.value) as sum
// now get the adjacent nodes we need to connect
MATCH (x)-[r1]->(a), (b)-[r2]->(y)
WITH x, y, sum + r1.value + r2.value AS sumValue
// making up relationship type and property name as I don't know what you're using
MERGE (x)-[:Rel{value: sumValue}]->(y)
Finally, when you're sure the new relationships look correct, delete the nodes you no longer need.
MATCH (n:ToDelete)
DETACH DELETE n

Complex neo4j cypher query to traverse a graph and extract nodes of a specific label and use them in optional match

I have a huge database of size 260GB, which is storing a ton of transaction information. It has Agent, Customer,Phone,ID_Card as the nodes. Relationships are as follows:
Agent_Send, Customer_Send,Customer_at_Agent, Customer_used_Phone,Customer_used_ID.
A single agent is connected to many customers .And hence hitting the agent node while querying a path is not feasible. Below is my query:
match p=((ph: Phone {Phone_ID : "3851308.0"})-[r:Customer_Send
| Customer_used_ID | Customer_used_Phone *1..5]-(n2))
with nodes(p) as ns
return extract (node in ns | Labels(node) ) as Labels
I am starting with a phone number and trying to extract a big "Customer" network. I am intentionally not touching the "Customer_at_Agent" relationship in the above networked query as it is not optimal as far as performance is concerned.
So, the idea is to extract all the "Customer" labeled nodes from the path and match it with [Customer_at_Agent] relationship.
For instance , something like:
match p=((ph: Phone {Phone_ID : "3851308.0"})-[r:Customer_Send
| Customer_used_ID | Customer_used_Phone *1..5]-(n2))
with nodes(p) as ns
return extract (node in ns | Labels(node) ) as Labels
of "type customer as c "
optional match (c)-[r1:Customer_at_Agent]-(n3)
return distinct p,r1
I am still new to neo4j and cypher and I am not able to figure out a hack to extract only "customer" nodes from the path and use that in the optional match.
Thanks in advance.
Use filter notation instead of extract and you can drop any nodes that aren't labelled right. Try out this query instead:
MATCH p = (ph:Phone {Phone_ID : "3851308.0"}) - [:Customer_Send|:Customer_used_ID|:Customer_used_Phone*1..5] - ()
WITH ph, [node IN NODES(p) WHERE node:Customer] AS customer_nodes
UNWIND customer_nodes AS c_node
OPTIONAL MATCH (c_node) - [r1:Customer_at_Agent] - ()
RETURN ph, COLLECT(DISTINCT r1)
So the second line takes the phone number and the path generated and gives you a list of nodes that have the Customer label as customer_nodes. You then unwind this list so you have individual nodes you can use in path matching. Line 4 performs your optional match and finds the r1 you're interested in, then line 5 will return the phone number node you started with and a collection of all of the r1 relationships that you found on customer nodes hooked up to that phone number.
UPDATE: I added some modifications to clean up your first query line as well. If you aren't going to use an alias (like r or n2 in the first line), then don't assign them in the first place; they can affect performance and cause confusion. Empty nodes and relationships are totally fine if you don't actually have any restrictions to place on them. You also don't need parentheses to mark off a path; they are used as a core part of Cypher's ASCII art to signify nodes, so I find they are more confusing than helpful.

Grouping nodes by their relationship

I've built a simple graph of one node type and two relationship types: IS and ISNOT. IS relationships means that the node pair belongs to the same group, and obviouslly ISNOT represents the not belonging rel.
When I have to get the groups of related nodes I run the following query:
"MATCH (a:Item)-[r1:IS*1..20]-(b:Item) RETURN a,b"
So this returns a lot of a is b results and I added some code to group them after.
What I'd like is to group them modifying the query above, but given my rookie level I haven't yet figured it out. What I'd like is to get one row per group like:
(node1, node3, node5)
(node2,node4,node6)
(node7,node8)
I assume what you call groups are nodes present in a path where all these nodes are connected with a :IS relationship.
I think this query is what you want :
MATCH p=(a:Item)-[r1:IS*1..20]-(b:Item)
RETURN nodes(p) as nodes
Where p is a path describing your pattern, then you return all the nodes present in the path in a collection.
Note that, a simple graph (http://console.neo4j.org/r/ukblc0) :
(item1)-[:IS]-(item2)-[:IS]-(item3)
will return already 6 paths, because you use undericted relationships in the pattern, so there are two possible paths between item1 and item2 for eg.

need help on cypher query

I need some help to do a cypher query.
In my neo4j databases I have element nodes which are linked by relation nodes (not relationship) and I would like to find all nodes that inherit from a node. For example if I have B-->A, c-->B and D-->A where "-->" means "inherit" I would like to retrieve B, C and D when I ask to retrieve which elements are inherit from A.
I already written a cypher query which is working well on a single level (where I replace "A" by the node id) :
Start
node=node(A)
match
(node)-[:IS_SOURCE_OF]->relation<-[:IS_TARGET_OF]-target
where
relation.relationType="INHERIT"
return target.uuid
This query returns B and D but I don't know how to return C as well.
Does someone can help me please ?
Thanks a lot
Cypher allows variable length matches on single relationships, but not the way you have designed your graph. To find the node c in your example you need to do:
Start node=node(A)
match (node)-[:IS_SOURCE_OF]->(r1)<-[:IS_TARGET_OF]-()-[:IS_SOURCE_OF]->(r2)<-[:IS_TARGET_OF]-(target)
where
r1.relationType="INHERIT" AND r2.relationType="INHERIT"
return target.uuid
However you should take a step back and rethink if you cannot model the inheritance relationship explicitly - in this case a single query catches all inherited nodes from a
start node=node(a)
match node-[:INHERITS*]->target
return target.uuid

How to check if there is a relationship between two nodes in a single DB transaction/Query?

I am using Java and would like to check if a relationship between two nodes exists and if so to retrieve the edge weights.
Is there a way to do it in one database call?
Thanks
In this case "variable length match" r becomes a collection of rels, instead of the usual single relationship.
start n1=node(1), n2=node(2)
match shortestPath(n1-[r*]-n2)
return extract(rel in r : r.weight)

Resources