Return Nodes related with a relatiohip to other Neo4j - neo4j

i have just started using Neo4j, and after creating the whole graph i'm trying to get all the nodes related to another one by a relatioship.
Match (n)-[Friendship_with]->({Name:"Gabriel"}) return n
That should give me the nodes that are friend of Gabriel, what i'm doing wrong?
I have used too this:
Match n-[r:Friendship_with]->n1 where n1.Name="Gabriel" return n
That give me some nodes, but some of then aren't directly related to Gabriel (for example, Maria is friend of Gabriel, she appears when i write that, but Alex who is friend of Maria and not from Gabriel, appear too)

This is weird.
Your query is correct.
I would suggest to check your data. Are you sure there isn't any direct connection between Alex and Gabriel ?
You could visualize your graph and see what is happening exactly in the neo4j browser. Just type a query with a bit more info like:
MATCH (n)-[f:Friendship_with]->(p {Name:"Gabriel"}) return n,f,p
and use the graph view to inspect your data.
EDIT:
As Pointed out by Michael, your first query is missing a colon in front of the specified relationship label "Friendship_with". So neo4j thinks it is a (rather long) variable name for your relationships, just as 'n' or 'n1'. It will thus retrieve anything that is connected to Gabriel without filtering by relationship label.
It doesn't explain though why you:
get the same results with the first and second query
get a 2nd degree relation as a result
so check your data anyway :)

You forgot the colon before :Friendship_with
Don't forget to provide labels, e.g. (n1:Person {Name:"Gabriel"})
Also some of your friendships might go in the other direction, so leave off the direction-arrow: Match (n:Person)-[Friendship_with]-(:Person {Name:"Gabriel"}) return n

Related

Directed search in Cypher and Neo4j Bloom

Given the following model:
Nodes: Host, Listener
Relations: Host -HOSTS-> Listener, Listener -CONNECTS_TO-> Listener
I want to perform a directed search on the CONNECTS_TO relation, to see the paths from host A to host B, but only if exists a listener on A that connects to a listener on B. Something like this:
(A:Host)-[:HOSTS]-(L_A:Listener)-[:CONNECTS_TO]->(L_B:Listener)-[:HOSTS]-(B:Host)
So for instance if I do have a relation L_A -CONNECTS_TO-> L_B, the query should return the path A->L_A->L_B<-B,
but if I also have a relation L_B-CONNECTS_TO->L_A the query should still return only the first path, since I'm looking for path from A to B, and if my only relation is the second one, the query should not return anything since A cannot connect to B, only B to A.
My Cypher query looks something like this, but still all the relations are returned:
match path=(A:Host)-[:HOSTS]-(L_A:Listener)-[:CONNECTS_TO*1]->(L_B:Listener)-[:HOSTS]-(B:Host)
where A.name = 'hostA' and B.name = 'hostB'
return path;
but Neo4j Browser still returns all the paths between A and B regardless of the CONNECTS_TO's direction. I also try to perform the same directed query in Bloom, but to no avail, so my questions are:
What might be wrong with my Cypher query?
Is it possible to perform this directed search in Bloom (as I cannot seem to see any directions there)?
Thank you!
LE: graph generation
create
(_0:`Host` {`name`:"hostA"}),
(_1:`Host` {`name`:"hostB"}),
(_2:`Host` {`name`:"hostC"}),
(_3:`Listener` {`name`:"listenerA"}),
(_4:`Listener` {`name`:"listenerB"}),
(_5:`Listener` {`name`:"listenerC"}),
(_0)-[:`HOSTS`]->(_3),
(_1)-[:`HOSTS`]->(_4),
(_2)-[:`HOSTS`]->(_5),
(_3)-[:`CONNECTS_TO`]->(_5),
(_3)-[:`CONNECTS_TO`]->(_4),
(_4)-[:`CONNECTS_TO`]->(_3),
(_5)-[:`CONNECTS_TO`]->(_4)
query for my only direct path between A and B:
match path=(source:Host)-[:HOSTS]-(l_source:Listener)-[:CONNECTS_TO*1]->(l_dest:Listener)-[:HOSTS]-(dest:Host) where source.name = 'hostA' and dest.name = 'hostB' return path;
https://console.neo4j.org/ here, it seems to work just fine, and at a closer look the json/text/table result in Neo4j Browser also seems correct, it's just that the visualization shows all the relations regardless of direction. Is there a way to display only the ones that I'm interested in? I know they can be interpreted as bi-directional, but in this case the direction it's quite important.
In Bloom, even though the search path is correct, and the number of nodes found is also correct, in this case 4 (hostA, listenerA, listenerB, hostB), all the nodes and relations are displayed, and this is what I'm trying to avoid, as our structure is very big, and we want to visualize certain paths only.
it's just that the visualization shows all the relations regardless of direction. Is there a way to display only the ones that I'm interested in?
If it is just the visualization, did you turn off the Connect result nodes feature in the browser?
With the option turned on I get:
Turned off:
For Bloom one option would be to put the query into a search phrase like this:
The resulting visualization will only show the query matching relationships:

Kevin path at neo4j

I am trying to discover how many hops I have to do to know a friend with Cipher. I have these relationships.
(Gutierrez)-[:Conhece]->(Felipe),
(Felipe)-[:Conhece]->(Gutierrez),
(Felipe)-[:Conhece]->(Fernando),
(Fernando)-[:Conhece]->(Felipe),
(Fernando)-[:Conhece]->(Pedro),
(Pedro)-[:Conhece]->(Fernando),
(Pedro)-[:Conhece]->(Arthur),
(Arthur)-[:Conhece]->(Pedro),
(Arthur)-[:Conhece]->(Vitor),
(Vitor)-[:Conhece]->(Arthur),
and when I execute my query it shows Fernando. What I want is to show only Vitor, Pedro and Arthur.
MATCH (n:Leitor)-[r:Conhece]-m
WHERE n.nome='Pedro' OR m.nome='Vitor'
RETURN n,r,m
with my Bacon Path query ->
Ok, I'm adding another answer because I think I understand what you want and it's different than my other answer.
If you want to find everybody that both Pedro and Vitor have met (in this case, just Author):
MATCH (pedro:Leitor)-[:Conhece]-(in_common:Leitor)-[:Conhece]-(vitor:Leitor)
WHERE pedro.nome='Pedro' AND vitor.nome='Vitor'
RETURN in_common
That also might look a bit better like this:
MATCH (pedro:Leitor {nome: 'Pedro'})-[:Conhece]-(in_common:Leitor)-[:Conhece]-(vitor:Leitor {name: 'Vitor'})
RETURN in_common
I also notice from your screenshots that every meeting has two relationships. That may very well be what you want, but if your plan was to always have two relationships whenever two people meet then you can get away with just one relationship. When you query bidirectionally (that is, without specifying direction like in the queries above) then you'll get relationships in either direction.
Normally you only want relationships going in both directions if the direction is important. That could be because your just recording that it goes from one node to another, or it could be because you're storing different values on the relationships.
Here you go:
MATCH shortestPath((n:Leitor)-[rels:Conhece*]-m)
WHERE n.nome IN ['Pedro', 'Vitor']
RETURN n,rels,m,length(rels)
In this case rels will be a collection of relationships because the path is variable length. You can also do:
MATCH path=shortestPath((n:Leitor)-[rels:Conhece*]-m)
WHERE n.nome IN ['Pedro', 'Vitor']
RETURN n,rels,m,length(rels),path,length(path)

Simple recursive CYPHER query

This is an extremely simple question, but reading through the docs for the first time, I can't figure out how to construct this query. Let's say I have a graph that looks like:
and additionally each person has an age associated with them.
What CYPHER query will get me a list of John's age and all the ages of the entire friend tree of John?
What I've tried so far:
MATCH (start)-[:friend]>(others)
WHERE start.name="John"
RETURN start.age, others.age
This has several problems,
It only goes one one one friend deep and I'd like to go to all friends of John.
It doesn't return a list, but a series of (john.age, other.age).
So what you need is not only friend of john, but also friends of friends. So you need to tell neo4j to recursively go deep in the graph.
This query goes 2 level deep.
MATCH (john:Person { name:"John" })-[:friend *1..2]->(friend: Person)
RETURN friend.name, friend.age;
To go n nevel deep, don't put anything i.e. *1..
Oh and I also found this nice example in neo4j
So what does *1..2 here means:
* to denote that its a recursion.
1 to denote that do not include john itself i.e. is the start node. If you put 0 here, it will also include the John node itself.
.. to denote that go from this node till ...
2 denotes the level of recursion. Here you say to stop at level 2. i.e. dont go beyond steve. If you put nothing there, it will keep on going until it cannot find a node that "has" a friend relationship
Documentation for these types of query match is here and a similar answer here.

How to query recommendation using Cypher

I'm trying to query Book nodes for recommendation by Cypher.
I want to recommend A:Book and C:Book for A:User.
i'm sorry I need some graph to explain this question, but I could't up graph image because my lepletion lacks for upload function.
I wrote query below.
match (u1:User{uid:'1003'})-->(o1:Order)-->(b1:Book)<--(o2:Order)
<--(u2:User)-->(o3:Order)-->(b2:Book)
return b2
This query return all Books(A,B,C,D) dispite cypher's Uniqueness.
I expect to only return A:Book and C:Book.
Is this behavior Neo4j' specification?
How do I get expected return? Thanks, everyone.
environment:
Neo4j ver.v2.0.0-RC1
Using Neo4j Server with REST API
Without the sample graph its hard to say why you get something back when you expected something else. You can share a sample graph by including a create statement that would generate said graph, or by creating it in Neo4j console and putting the link in your question. Here is an example of the latter: console.neo4j.org/r/fnnz6b
In the meantime, you probably want to declare the type of the relationships in your pattern. If a :User has more than one type of outgoing relationships you will be excluding those other paths based on the labels of the nodes on the other end, which is much less efficient than to only traverse the right relationships to begin with.
To my mind its not clear whether (u:User)-->(o:Order)-->(b:Book) means that a user has one or more orders, and each order consists of one or more books; or if it means only that a user ordered a book. If you can share a sample, hopefully that will be clear too.
Edit:
Great, so looking at the graph: You get B and D back because others who bought B also bought D, and others who bought D also bought B, which is your criterion for recommendation. You can add a filter in the WHERE clause to exclude those books that the user has already bought, something like
WHERE NOT (u1)-[:BUY]->()-[:CONTAINS]->(b2)
This will give you A, C, C back, since there are two matching paths to C. It's probably not important to get two result items for C, so you can either limit the return to give only distinct values
RETURN DISTINCT(b2)
or group the return values by counting the matching paths for each result as a 'recommendation score'
RETURN b2, COUNT(b2) as score
Also, if each order only [CONTAINS] one book, you could try modelling without order, just (:User)-[:BOUGHT]->(:Book).

Returning all relationships for a list of nodes

This is quite a general question but to make it more understandable I'll give it a bit of context.
In neo4j I have a series of words (nodes) that are associated with one another. I want to specify a list of nodes and the Cypher query return a list of any relationships between those nodes.
The nodes specified in the list are all guaranteed to have at least one relationship to another node specified in the list.
I created a query to do this and in certain circumstances it works fine - http://console.neo4j.org/?id=s30cbm
Unfortunately, when I add the words 'bark' and 'dog' to the list I get an 'unexpected traversal state encountered' error message. I presume this is because the database cursor has got to the fruit node and then there's no relationship between that and bark, even though there is a relationship from tree to bark. http://console.neo4j.org/?id=258d6g
I'm obviously doing the query slightly wrong and any advice would be appreciated on how I can rectify this.
This works in the latest console (your second link), btw, so it looks like they fixed it. Looks like it should be working in 1.9-M04+.

Resources