Env - Neo4j 4.0 enterprise
Plugins - GDS and apoc
I have a data in neo4j like below -
CREATE (a:hotel {hotel_id:'A'}),
(b:hotel {hotel_id:'B'}),
(c:hotel {hotel_id:'C'}),
(d:hotel {hotel_id:'D'}),
(e:hotel {hotel_id:'E'}),
(f:hotel {hotel_id:'F'}),
(g:hotel {hotel_id:'G'}),
(h:hotel {hotel_id:'H'}),
(i:hotel {hotel_id:'I'}),
(a)-[:HAS]->(b),
(b)-[:HAS]->(c),
(c)-[:HAS]->(d),
(d)-[:HAS]->(e),
(e)-[:HAS]->(f),
(f)-[:HAS]->(g),
(g)-[:HAS]->(h),
(h)-[:HAS]->(i),
(ap:hotel_loc {loc_id:'pp1A'}),
(bp:hotel_loc {loc_id:'pp1B'}),
(cp:hotel_loc {loc_id:'pp1C'}),
(dp:hotel_loc {loc_id:'pp1D'}),
(ep:hotel_loc {loc_id:'pp1E'}),
(fp:hotel_loc {loc_id:'pp1F'}),
(gp:hotel_loc {loc_id:'pp1G'}),
(hp:hotel_loc {loc_id:'pp1H'}),
(ip:hotel_loc {loc_id:'pp1I'}),
(a)-[:HAS_JUNC]->(ap),
(b)-[:HAS_JUNC]->(bp),
(c)-[:HAS_JUNC]->(cp),
(d)-[:HAS_JUNC]->(dp),
(e)-[:HAS_JUNC]->(ep),
(f)-[:HAS_JUNC]->(fp),
(g)-[:HAS_JUNC]->(gp),
(h)-[:HAS_JUNC]->(hp),
(i)-[:HAS_JUNC]->(ip);
2 scenerios
1. List of the all node starting from
given a loc_id (example pp1F), i need to get all the nodes(hotel) and their associated :HAS_JUNC nodes.
f,pp1F
g,pp1G
h,pp1H
i,pp1I
List of all until the end.
given a loc_id (example pp1C), i need to all the nodes until pp1C
a,pp1A
b,pp1B
c,pp1C
I tried this query, but no results -
MATCH s= (h1:hotel)-[:HAS_PROPERTY]->(start:hotel_propert {property_id:"pp1A"}),
e= (h2:hotel)-[:HAS_PROPERTY]->(end:hotel_propert {property_id:"pp1C"})
WITH h1, h2, s,e match p=(h1)-[:HAS*]->(h2) RETURN s,p,e
Any help is highly appreciated.
To get the hotels that have a direct HAS_JUNC relationship to a specific hotel_loc (whose id is assumed to be in the loc_id parameter) :
MATCH (a:hotel)-[:HAS_JUNC]->(ap)
WHERE ap.loc_id = $loc_id
RETURN ap, COLLECT(a) AS directly_connected_hotels
To get all the hotels connected to a specific hotel_loc:
MATCH (a:hotel)-[:HAS *0..]->()-[:HAS_JUNC]->(ap)
WHERE ap.loc_id = $loc_id
RETURN ap, COLLECT(a) AS connected_hotels
In the variable-length relationship pattern [:HAS *0..], the 0 lower bound means that the pattern is allowed to match paths in which the HAS relationship does not exist.
Related
According to this post I tried to map all related entities in a list.
I used the same query into the post with a condition to return a list of User but it returns duplicate object
MATCH (user:User) WHERE <complex conditions>
WITH user, calculatedValue
MATCH p=(user)-[r*0..1]-() RETURN user, calculatedValue, nodes(p), rels(p)
Is it a bug? I'm using SDN 4.2.4.RELEASE with neo4j 3.2.1
Not a bug.
Keep in mind a MATCH in Neo4j will find all occurrences of a given pattern. Let's look at your last MATCH:
MATCH p=(user)-[r*0..1]-()
Because you have a variable match of *0..1, this will always return at least one row with just the user itself (with rels(p) empty and nodes(p) containing only the user), and then you'll get a row for every connected node (user will always be present on that row, and in the nodes(p) collection, along with the other connected node).
In the end, when you have a single user node and n directly connected nodes, you will get n + 1 rows. You can run the query in the Neo4j browser, looking at the table results, to confirm.
A better match might be something like:
...
OPTIONAL MATCH (user)-[r]-(b)
RETURN user, calculatedValue, collect(r) as rels, collect(b) as connectedNodes
Because we aggregate on all relationships and connected nodes (rather than just the relationships and nodes for each path), you'll get a single row result per user node.
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.
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.
I have created a graph db in Neo4j and want to use it for generalization purposes.
There are about 500,000 nodes (20 distinct labels) and 2.5 million relations (50 distinct types) between them.
In an example path : a -> b -> c-> d -> e
I want to find out the node without any incoming relations (which is 'a').
And I should do this for all the nodes (finding the nodes at the beginning of all possible paths that have no incoming relations).
I have tried several Cypher codes without any success:
match (a:type_A)-[r:is_a]->(b:type_A)
with a,count (r) as count
where count = 0
set a.isFirst = 'true'
or
match (a:type_A), (b:type_A)
where not (a)<-[:is_a*..]-(b)
set a.isFirst = 'true'
Where is the problem?!
Also, I have to create this code in neo4jClient, too.
Your first query will only match paths where there is a relationship [r:is_a], so counting r can never be 0. Your second query will return any arbitrary pair of nodes labeled :typeA that aren't transitively related by [:is_a]. What you want is to filter on a path predicate. For the general case try
MATCH (a)
WHERE NOT ()-->a
This translates roughly "any node that does not have incoming relationships". You can specify the pattern with types, properties or labels as needed, for instance
MATCH (a:type_A)
WHERE NOT ()-[:is_a]->a
If you want to find all nodes that have no incoming relationships, you can find them using OPTIONAL MATCH:
START n=node(*)
OPTIONAL MATCH n<-[r]-()
WITH n,r
WHERE r IS NULL
RETURN n
I am using Neo4j 2.0 and using the following query to find out the count of number of a particular relationship from a particular node.
I have to check the number of relationships named "LIVES" from a particular node PERSON.
My query is:
match (p:PERSON)-[r:LIVES]->(u:CITY) where count(r)>1
return count(p);
The error shown is:
SyntaxException: Invalid use of aggregating function count(...)
How should I correct it?
What you want is a version of having? People living in more than one city?
MATCH (p:PERSON)-[:LIVES]->(c:CITY)
WITH p,count(c) as rels, collect(c) as cities
WHERE rels > 1
RETURN p,cities, rels