relationship exists between entity list - neo4j

Relationship between two users can be found out using below query.
RETURN EXISTS( (:User{_id:'User/123'})-[:Link]-(:User{_id:'User/567'}) )
What if it needs to be run for the list of queries like for below query i want to check if relationship exists
MATCH p=(u:User{_id:'User/8199'})-[r:Link]-(u1:User)
WHERE u1._id in ['12317291','User/09563','User/392942','User/24974','User/720']
RETURN p

You could match the first use and then iterate through the lest and test for existence for each other user in the list.
MATCH (u:User {_id: 'User/8199'})
WITH u
UNWIND ['12317291','User/09563','User/392942','User/24974','User/720'] | u1] AS other_user
RETURN other_user, exists((u)-[:Link]->(:Test {name: other_user}))
Or you could do something like this if you wanted the actual users matched afterwards. Match the first user, test for a realtioship to a list of users and return a collection of matches.
MATCH (u:User {_id: 'User/8199'})
RETURN [(u)-[:Link]->(u1:User)
WHERE u1._id IN
['12317291','User/09563','User/392942','User/24974','User/720'] | u1] AS matches

Related

Issues writing a query that would fetch the second degree friends of Abiodun considering the pattern and the relationships

As a newbie, I am trying to write a cypher query that would fetch the second-degree friends of Abiodun(node) considering the pattern and the relationships.
Initial codes
1) CREATE (abiodun:Person {name:"Abiodun"})
RETURN abiodun
2) MATCH (abiodun:Person {name:"Abiodun"})
CREATE (abiodun)-[like:LIKE]->(neo:Database {name:"Neo4j" })
RETURN abiodun,like,neo
3)MATCH (abiodun:Person {name:"Abiodun"})
FOREACH (name in ["Rajesh","Anna","Julia","Andrew"] |
CREATE (abiodun)-[:FRIEND]->(:Person {name:name}))
4)MATCH (neo:Database {name:"Neo4j"})
MATCH (anna:Person {name:"Anna"})
CREATE (anna)-[:FRIEND]->(:Person:Expert {name:"Amanda"})-[:WORKED_WITH]->(neo) here
Actual issue(what i did so far
MATCH (abiodun) WHERE not ((abiodun)-[:FRIEND]->(myFriends))
RETURN n
I am trying to write a query that will display only Amanda
You can use a fixed length relationship from Abiodun to Amanda.
The meaning of "*2" in the relationship is "give me a friend of friend of Abiodun".
MATCH (:Person {name: "Abiodun"}) - [:FRIEND*2] -> (p:Person)
RETURN p
This is found in details here: https://neo4j.com/docs/cypher-manual/current/clauses/match/#varlength-rels

Neo4J Matching Nodes Based On Relationships

I have the following statement:
MATCH path=(p:Person {person_id: '123'})-[:ASSOCIATED_WITH]-(:Person)
where exists((p)-[:BELONGS]-(:Face)-[:CORRESPONDS]-(:Image)-[:HAS_ACCESS_TO]-(:Dias {group_name: 'group'}))
RETURN path
It returns 3 nodes, 2 relationships. This is what I would like to happen but the group_name I will actually be passing is an array. How do I add the condition to check for the value in the array while still maintaining 3 nodes and two relationships? The only relationship I want to return back is ASSOCIATED_WITH. The 3 nodes being, the main person_id of "123" and the two associated persons.
I will assume you pass the list of group names in a names parameter.
If you want to get the paths in which the EXISTS test succeeds for ANY name in the list:
MATCH (p:Person {person_id: '123'})
WHERE ANY(x IN $names WHERE
EXISTS((p)-[:BELONGS]-(:Face)-[:CORRESPONDS]-(:Image)-[:HAS_ACCESS_TO]-(:Dias {group_name: x})))
MATCH path=(p)-[:ASSOCIATED_WITH]-(:Person)
RETURN path
Or, if you want to get the paths in which the EXISTS test succeeds for ALL names in the list, just replace ANY in the above request with ALL:
MATCH (p:Person {person_id: '123'})
WHERE ALL(x IN $names WHERE
EXISTS((p)-[:BELONGS]-(:Face)-[:CORRESPONDS]-(:Image)-[:HAS_ACCESS_TO]-(:Dias {group_name: x})))
MATCH path=(p)-[:ASSOCIATED_WITH]-(:Person)
RETURN path

How to do multiple Match statements, or join two queries with the same keyname

A user can be friends with another user. A user can also follow a users profile page. I want to query on all friends and followed_users (users who own the followed profile page)
This return the followed_users
match (user:User {id: SOME_ID})
-[:FOLLOWED_PAGE]->(Page)<-[:PROFILE_PAGE]-(followed_user:User)
return followed_user
This return the friend
match (u:User {uuid: SOME_ID})-[:CONNECTED_USER]->(friend:User)
return friend
This will union both
match (user:User {id: SOME_ID})
-[:FOLLOWED_PAGE]->(Page)<-[:PROFILE_PAGE]-(followed_user:User)
return followed_user
UNION ALL match (u:User {uuid: SOME_ID})-[:CONNECTED_USER]->(friend:User)
return friend
The problem is, I want to keep querying. Union will return.
This is what I WANT to do, but it doesnt work (the second match overwrites the first one)
match (user:User {id: SOME_ID})
-[:FOLLOWED_PAGE]->(Page)<-[:PROFILE_PAGE]-(friend:User)
match (user)-[:CONNECTED_USER]->(friend:User)
WHERE (page:Page)<-[:COMMENTED_ON]-(friend)
return page
How can I do something like this?
EDIT: Stefan Armbruster
Initial setup query:
create (PP:Page {title: "Jim"}), (Jim:User {name: "Jim"}), (You:User {name: "You"}), (Frank:User {name: "Frank"}), (Jimpost:Post {title: "Jim posted this, You follow his page"}), (Frankpost:Post {title: "Frank posted this, You are his friend (connected_to)"}),
(You)-[:CONNECTED_USER]->(Frank),
(Frank)-[:CONNECTED_USER]->(You),
(You)-[:BOOKMARKED_PAGE]->(PP),
(PP)<-[:PROFILE_PAGE]-(Jim),
(Jimpost)<-[:POSTED]-(Jim),
(Frankpost)<-[:POSTED]-(Frank)
You are "You". Frank is your "Friend" (CONNECTED_USER). You bookmarked "Jim"'s ProfilePage (Page). So I would like to be able to query using both "Friends" and "Followed" (Users whos profile pages a user has bookmarked) users. In this instance they have both posted a page, but the use case is not unique to just posted pages
You need to use the comma , to create composite patterns:
match (user:User {id: SOME_ID})-[:FOLLOWED_PAGE]->(Page)<-[:PROFILE_PAGE]-(friend:User),
(user)-[:CONNECTED_USER]->(friend:User),
(page:Page)<-[:COMMENTED_ON]-(friend)
return page
The comma basically build up one single pattern. The separate parts are connected by commonly used identifiers (here user, page, friend).

Neo4j how to create/delete relationships from a set of nodes ids

I have a User nodes and Intersets node. I want to be able given an array of interests to create/delete/change the relationship between the User and the Interests I also want in the same query to update some properties on the user node.
So far this is what i have menage to do:
MATCH (user:User {id: id})
OPTIONAL MATCH (user)-[oldRel:InterestedIn]->(:Interest)
DETACH DELETE oldRel
WITH user
UNWIND {interestsIds} as id
MATCH (interest:Interest {id: id})
MERGE (user)-[rel: InterestedIn]->(interest)
SET user.name = {user}.name, ..(more sets)
RETURN user, collect(interest) as interests
I think this one is working tho some time is looks like the interests are returned duplicated..
As well this query looks like a bit of an overkill. Any idea how to do that query with a better way?
Does this seem about right?
MATCH (user:User {id: id})
OPTIONAL MATCH (interest:Interest)
WHERE interest.id IN {interestsIds}
MERGE (user)-[:InterestedIn]->(interest)
WITH DISTINCT user
MATCH (user)-[rel:InterestedIn]->(interest:Interest)
WHERE NOT(interest.id IN {interestsIds})
DELETE rel
WITH DISTINCT user
MATCH (user)-[:InterestedIn]->(interest:Interest)
RETURN user, collect(interest)

Cypher: How to return a node if the relationship doesn't exist?

I have User and Building labels for nodes, the relationships are User-[:HAS_PERMISSION]->Building
To get all buildings that a user is having permissions to so I use MATCH (u:User {id: {id}}),(u)-[r:HAS_PERMISSION]->(b:Building) return b
How can I just return the user in case he exists and there are no relationships? (basically I also want to know if the user exists at all..)
Not sure if I understand your question correctly, but I think you'll need an OPTIONAL MATCH. This query shows all users with or without access to a building.
MATCH (u:User)
OPTIONAL MATCH (u)-[r:HAS_PERMISSION]->(b:Building)
RETURN u, b
Or maybe your requirement is simpler. If you just want all users, there's no need to use pattern matching:
MATCH (u:User)
RETURN u

Resources