I have written below three queries and trying to understand difference between all 3 of them.
Query1:
MATCH (person)-[r]->(otherPerson)
Query2:
MATCH (person)-->(otherPerson)
Query3:
MATCH (person)--(otherPerson)
Please let me know if there is any difference between the three queries.
Query 1 and 2 are basically the same, you are asking for all nodes connected by relationships that start at the person nodes and end at the otherPerson node. In Query 1 you are also adding an alias/label to the actual relationship r that would allow you to return the relationship. In Query 1 you could do
MATCH (person)-[r]->(otherPerson) RETURN r
In Query 2, you could not return the relationship.
Query 3 is similar to Query 2 except that you are asking for all nodes connected by relationships that start or end at the person nodes and start or end at the otherPerson node.
Query 1 and 2 will find all nodes and give them a label of person. It will then go out all outbound relationships and label the connected node as otherPerson. In the case of Query 1 the relationship will also be given a label of r.
Query 3 will match the same pattern except it will traverse both incoming and outgoing edges to find the otherPerso node.
Related
I am a newbie who just started learning graph database and I have a problem querying the relationships between nodes.
My graph is like this:
There are multiple relationships from one node to another, and the IDs of these relationships are different.
How to find relationships where the number of relationships between two nodes is greater than 2,or is there a problem with the model of this graph?
Just like on the graph, I want to query node d and node a.
I tried to use the following statement, but the result is incorrect:
match (from)-[r:INVITE]->(to)
with from, count(r) as ref
where ref >2
return from
It seems to count the number of relations issued by all from, not the relationship between from-->to.
to return nodes who have more then 2 relationship between them you need to check the size of the collected rels. something like
MATCH (x:Person)-[r:INVITE]-(:Party)
WITH x, size(collect(r)) as inviteCount
WHERE inviteCount > 2
RETURN x
Aggregating functions like COLLECT and COUNT use non-aggregating terms in the same WITH (or RETURN) clause as "grouping keys".
So, here is one way to get pairs of nodes that have more than 2 INVITE relationships (in a specific direction) between them:
MATCH (from)-[r:INVITE]->(to)
WITH from, to, COUNT(r) AS ref
WHERE ref > 2
RETURN from, to
NOTE: Ideally (for clarity and efficiency), your nodes would have specific labels and the MATCH pattern would specify those labels.
Given that I'm very new to Neo4j. I have a schema which looks like the below image:
Here Has nodes are different for example Passport, Merchant, Driving License, etc. and also these nodes are describing the customer node (looking for future scope of filtering customers based on these nodes).
SIMILAR is a self-relation meaning there exists a customer with ID:1 is related to another customer with ID:2 with a score of 2800.
I have the following questions:
Is this a good schema given the condition of the future scope I mentioned above, or getting all the properties in a single customer node is viable? (Different nodes may have array of items as well, for example: ()-[:HAS]->(Phone) having {active: "+91-1231241", historic_phone_numbers: ["+91-121213", "+91-1231421"]})
I want to get the customer along with describing nodes in relation to other customers. For that, I tried the below query (w/o number of relation more than 1):
// With number_of_relation > 1
MATCH (searched:Customer)-[r:SIMILAR]->(matched:Customer)
WHERE r.score > 2700
WITH searched, COLLECT(matched.customer_id) AS MatchedList, count(r) as cnt
WHERE cnt > 1
UNWIND MatchedList AS matchedCustomer
MATCH (person:Customer {customer_id: matchedCustomer})-[:HAS|:LIVES_IN|:IS_EMPLOYED_BY]->(related)
RETURN searched, person, related
Result what I got is below, notice one customer node not having its describing nodes:
// without number_of_relation > 1
// second attempt - for a sample customer_id
MATCH (matched)<-[r:SIMILAR]-(c)-[:HAS|:LIVES_IN|:IS_EMPLOYED_BY]->(b)
WHERE size(keys(b)) > 0
AND c.customer_id = "1b093559-a39b-4f95-889b-a215cac698dc"
AND r.score > 2700
RETURN b AS props, c AS src_cust, r AS relation, matched
Result I got are below, notice related nodes are not having their describing nodes:
If I had two describing nodes with some property (some may have a list) upon which I wanted to query and build the expected graph specified in point 2 above, how can I do that?
I want the database to find a similar customer given the describing nodes. Example: A customer {name: "Dave"} has phone {active_number: "+91-12345"} is similar to customer {name: "Mike"} has phone {active_number: "+91-12345"}. How can get started with this?
If something is unclear, please ask. I can explain with examples.
[EDITED]
Yes, the schema seems fine, except that you should not use the same HAS relationship type between different node label pairs.
The main problem with your first query is that its top MATCH clause uses a directional relationship pattern, ()-->(), which does not allow all Customer nodes to have a chance to be the searched node (because some nodes may only be at the tail end of SIMILAR relationships). This tweaked query should work better:
MATCH (searched:Customer)-[r:SIMILAR]-(matched:Customer)
WHERE r.score > 2700
WITH searched, COLLECT(matched) AS matchedList
WHERE SIZE(matchedList) > 1
UNWIND matchedList AS person
MATCH (person)-[:HAS|LIVES_IN|IS_EMPLOYED_BY]->(pDesc)
WITH searched, person, COLLECT(pDesc) AS personDescribers
MATCH (searched)-[:HAS|LIVES_IN|IS_EMPLOYED_BY]->(sDesc)
RETURN searched, person, personDescribers, COLLECT(sDesc) AS searchedDescribers
It's not clear what you want are trying to do.
To get all Customers who have the same phone number:
MATCH (c:Customer)-[:HAS_PHONE]-(p:Phone)
WHERE p.activeNumber = '+91-12345'
WITH p.activeNumber AS phoneNumber, COLLECT(c) AS customers
WHERE SIZE(customers) > 1
RETURN phoneNumber, customers
I am trying to write a cypher query in neo4j for the following scenario:
Suppose there are n nodes, each node has a relationship with all the other nodes and the relationship has a weight(less than 1 and as type float).
Ex: there are 6 nodes, p1,p2,p3,p4,p5,p6 and there is weight for p1-p3,p2-p3,p1-p2 ... (nCr relationships). If I give a parameter as "p2" and ask to fetch the connecting nodes with the score in descending order(like top 3 nodes).
I am unable to think of any solution for now. The actual number of nodes is 45 and I need 4 connecting nodes to a particular node.
Example below:
suppose the following is my CSV for products:
1,Chai
2,Chang
3,Aniseed Syrup
4,Chef Anton's Cajun Seasoning
5,Chef Anton's Gumbo Mix
and a snippet for their relationships(not writing the complete list because it is nCr and it would be too long):
1,2,0.0
1,3,0.5364545606371
1,4,0.63314842736745
1,5,0.15688579582258
2,3,0.0
2,4,0.0
2,5,0.0
2,6,0.0
I ran the following query to create the nodes and their relation:
LOAD CSV FROM 'file:///products.csv' AS row
WITH toInteger(row[0]) AS productId, row[1] AS productName
MERGE (p:Product {productId: productId})
SET p.productName = productName
RETURN count(p)
LOAD CSV FROM 'file:///mapping.csv' AS row
WITH toInteger(row[0]) AS productId1,toInteger(row[1]) as productId2,toFloat(row[2]) as score
MATCH (p1:Product {productId: productId1})
MATCH (p2:Product {productId: productId2})
MERGE (p1)-[rel:SCORE {score:score}]-(p2)
RETURN count(rel)
Now if I want to query let's say neighbors of node "2" with weights in decreasing order(LIMIT x - I can define the limit), I am unable to write the query for this.
You can combine an ORDER BY with a LIMIT query to get the higher weights.
I don't know how you data is being mapped, but you can run the query ordering by the relationship weights and limit the query by 3 results. So you will have what you need.
I believe this tutorial can help:
https://www.tutorialspoint.com/neo4j/neo4j_limit_clause.htm
Like I have a node by label person
Then there are some alternate nodes attached to it by some relation for the time being I don't know the relation. What I want through report is to know the orphaned nodes in neo4j i.e those that don't have relationship with the Person node or if their relation status property is inactive so its of no use.
I want to create that report in order to remove the orphaned/unused nodes
I have to create a report that should include the following types of nodes.
1. Get All active Alternate Nodes means nodes that have status as Confirmed.
a. Which do not have any incoming relationships.
Or
b. No active incoming relationships means the status property of relationship is not confirmed.
The case is I don't know what relationship is between them I have to just check with or without relationship
I tried cypher query but didn't worked for unknown relationship
I don't see your graph so I created a sample. See below.
If you want to collect all Alona and Inactive nodes, then you can write your query as:
match (n)
where not (n) <--()
and (n.Status = 'Confirmed' or n.Status != 'Confirmed')
return n
which simplifies into:
match (n)
where not (n) <--()
return n
Result:
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.