why my cypher query return null? - neo4j

I have two structure with different label:
tree node's label:Person
graph nodes'label:Friend
1)tree:
a-->b-->d
| |
| -->e
|
-->c-->f
|
-->g
|
-->h
2)graph:
b-->a-->f-->g-->b
|
-->b
I have this cypher query and what i expect return is : "b"
but it return null. how I must write this query????
MATCH (a),(b)
WHERE a.name='ali'
AND (a:Friend)-[:FRIEND_OF]-(b:Friend)
AND (a:Person)-[:PARENT_OF]->(b:Person)
RETURN b.name

It would help a lot if you could explain what you're trying to do. I don't really understand.
Since the relationship between people already has tags (FRIEND_OF, PARENT_OF), why would you use a Friend node label? Unless you have a good reason, I would just have nodes with a Person tag.
The query you posted will return person nodes who are friends with ali and where Ali is his/her parent. It can be rewritten to:
MATCH (a:Person {name:"ali"})-[:FRIEND_OF]-(b:Person)
WHERE (a)-[:PARENT_OF]->(b)
RETURN b.name
I don't have your data set so it's hard to test for the results. You are stating that you are not getting any results.
Can you verify that:
There is only one node with name ali and it has the 2 relationships you are looking for? If there are 2 nodes with name ali and each of them has one of the afore mentioned relationships Neo4j won't find any matches. You are looking for exactly one node which has both relationships.
Node b exists and has a name property?

Related

How to return distinct nodes based on relationship?

In the movie database, I created a self relationship(ACTED_WITH) on the Person node using the Cypher query.
MATCH (p1:Person)-[:ACTED_IN]->(m:Movie)
MATCH (p2:Person)-[:ACTED_IN]->(m)
WHERE p2 <> p1
OPTIONAL MATCH (p1)-[r:ACTED_WITH]-(p2)
FOREACH (n IN (CASE WHEN r IS NULL THEN [0] ELSE [] END) |
MERGE (p1)-[:ACTED_WITH]-(p2)
)
I want to return all the actors of the movie (Cloud Atlas) having ACTED_WITH relationship without duplicates?
This is the Cypher Query, I tried
MATCH (m)-[:ACTED_IN]-(a1)-[r]-(a2)-[:ACTED_IN]-(m)
WHERE m.title="Cloud Atlas" RETURN a1,a2
The query returns Tom Hanks and Hugo Weaving twice (may be due to bidirectional relationship?).
"a1","a2"
{"name":"Tom Hanks","born":1956}, {"name":"Hugo Weaving","born":1960}
{"name":"Hugo Weaving","born":1960}, {"name":"Tom Hanks","born":1956}
Expected results
"a1", "a2"
{"name":"Tom Hanks","born":1956}, {"name":"Hugo Weaving","born":1960}
How, can I alter my query so that Tom Hanks and Hugo Weaving is returned only once? Any insight in the right direction is highly appreciated. Thank you.
Use Directed and Named (In case there are other relationships between persons) relationship between Actor nodes:
MATCH (m:Movie)<-[:ACTED_IN]-(a1:Person)-[r:ACTED_WITH]->(a2:Person)-[:ACTED_IN]->(m)
WHERE m.title="Cloud Atlas" RETURN a1,a2
Suggestion: Use Label names for better performance and readability
You can try to add direction in your query
MATCH (m)-[:ACTED_IN]-(a1)-[r]->(a2)-[:ACTED_IN]-(m)
WHERE m.title="Cloud Atlas" RETURN a1, a2
It works on my dataset, but it won't work if you have duplicate relationships in both directions.
On other hand, have duplicate relationships seems not good practice, you can read more here.

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.

Return Neo4J Combined Relationships When Searching Across Several Relationship Types

I would like to query for various things and returned a combined set of relationships. In the example below, I want to return all people named Joe living on Main St. I want to return both the has_address and has_state relationships.
MATCH (p:Person),
(p)-[r:has_address]-(a:Address),
(a)-[r1:has_state]-(s:State)
WHERE p.name =~ ".*Joe.*" AND a.street = ".*Main St.*"
RETURN r, r1;
But when I run this query in the Neo4J browser and look under the "Text" view, it seems to put r and r1 as columns in a table (something like this):
│r │r1 │
╞═══╪═══|
│{} │{} │
rather than as desired with each relationship on a different row, like:
Joe Smith | has_address | 1 Main Street
1 Main Street | has_state | NY
Joe Richards | has_address | 22 Main Street
I want to download this as a CSV file for filtering elsewhere. How do I re-write the query in Neo4J to get the desired result?
You may want to look at the Cypher cheat sheet, specifically the Relationship Functions.
That said, you have variables on all the nodes you need. You can output all the data you need on each row.
MATCH (p:Person),
(p)-[r:has_address]-(a:Address),
(a)-[r1:has_state]-(s:State)
WHERE p.name =~ ".*Joe.*" AND a.street = ".*Main St.*"
RETURN p.name AS name, a.street AS address, s.name AS state
That should be enough.
What you seem to be asking for above is a way to union r and r1, but in such a way that they alternate in-order, one row being r and the next being its corresponding r1. This is a rather atypical kind of query, and as such there isn't a lot of support for easily making this kind of output.
If you don't mind rows being out of order, it's easy to do, but your start and end nodes for each relationship are no longer the same type of thing.
MATCH (p:Person),
(p)-[r:has_address]-(a:Address),
(a)-[r1:has_state]-(s:State)
WHERE p.name =~ ".*Joe.*" AND a.street = ".*Main St.*"
WITH COLLECT(r) + COLLECT(r1) as rels
UNWIND rels AS rel
RETURN startNode(rel) AS start, type(rel) AS type, endNode(rel) as end

Cypher: Find relationships of nodes with connected parents

I'm hoping this diagram will be sufficient to explain what I'm after:
true
a--------------------b
| |
parent | | parent
| |
a_e------------------b_e
experimental
nodes a_e and b_e are experimental observations that each have only one parent, a and b, respectively. I know a true relationship exists between a and b, and I want to find cases where experimental relationships were observed between a_e and b_e. Among other things, I tried the following:
MATCH (n)-[:true]-(m)
WITH n,m
MATCH (n)-[:parent]-(i)
MATCH (m)-[:parent]-(j)
WITH i,j
OPTIONAL MATCH (i)-[r]-(j)
RETURN r
but this returns no rows. I'm thinking of this like a nested loop, matching all possible relationships between all i's and all j's. Is this type of query possible?
Something like
match (n)-[:true]-(m)
match (n)-[:parent]->(n_child)-[:experimental]-(m_child)<-[:PARENT]-(m)
return n_child,m_child
(not tested)
Assuming this is an example and you have labels etc. on your nodes.

Fixing inconsistent Cypher results in Neo4j

I've been getting some strange results with a Neo4j database I made (version 2.1.0-M01). I have a graph with the following relationship:
Node[211854]{name : "dst"} <-[:hasrel]- Node[211823]{name : "src"}
I've confirmed this relationship using the following query:
START m=node(211854) MATCH (m)<-[r]-(n) RETURN m,r,n;
which returns a one row result, as expected:
| m | r | n
| Node[211854] | :hasrel[225081] | Node[211823]
The following query returns nothing, however:
START n=node(211823) MATCH (m)<-[r]-(n) RETURN m,r,n
Any thoughts on what might be happening? I've run these queries with and without indexes on the name properties for the nodes.
EDIT: Fixed typo with initial node number.
EDIT2: I rebuilt the server and both queries return the results I expect. Perhaps the error was corruption in the first database?
Using the node id's is not such a good idea, you can use the properties on your node to query them.
For example:
MATCH (m)<-[r]-(n {name: "src"}) RETURN m,r,n;
Does that query return what you expected?
You have to invert the relationship-direction. As you are looking for incoming relationships for your node 211823, this is not one of them. It's an outgoing relationship.
Please also update your database to the current version: 2.1.2 http://neo4j.org/download
START n=node(211823) MATCH (m)-[r]->(n) RETURN m,r,n
Perhaps you should give your nodes and relationships more descriptive names, so you spot easier when you inverted a domain concept.

Resources