I have the following Neo4j scenario (I am using Neo4j 2.0.1):
Nodes:
User
Token
Relationships:
friends_with -> bidirectional relationship between Users
is_authorized_by -> directed relationship between a User and a Token
For each User, I need to get either its Token (if it has a valid one), or a valid friend's Token.
I've written the following Cypher query:
MATCH (user:User) WHERE user.id IN ['123', '456']
OPTIONAL MATCH (user)-[:is_authorized_by]->(user_token:Token)
WHERE HAS (user_token.access_token) AND timestamp()/1000 < user_token.expiration_timestamp
OPTIONAL MATCH (user)-[:friends_with*1..3]-(friend:User)-[:is_authorized_by]->(friend_token:Token)
WHERE HAS (friend_token.access_token) AND timestamp()/1000 < friend_token.expiration_timestamp
RETURN user.id as userId, coalesce(user_token.access_token, friend_token.access_token) AS token
Of course, this doesn't work, as the second OPTIONAL MATCH doesn't only match the first friend's Token.
What I would like to do is:
MATCH (user:User) WHERE user.id IN ['123', '456']
OPTIONAL MATCH (user)-[:is_authorized_by]->(user_token:Token)
WHERE HAS (user_token.access_token) AND timestamp()/1000 < user_token.expiration_timestamp
OPTIONAL MATCH (user)-[:friends_with*1..3]-(friend:User)-[:is_authorized_by]->(friend_token:Token)
WHERE HAS (friend_token.access_token) AND timestamp()/1000 < friend_token.expiration_timestamp <--- limit this to 1
RETURN user.id as userId, coalesce(user_token.access_token, friend_token.access_token) AS token
How can this be achieved?
Edit 1:
I'm only interested in direct friends' Tokens:
MATCH (user:User) WHERE user.id IN ['123', '456']
OPTIONAL MATCH (user)-[:is_authorized_by]->(user_token:Token)
WHERE HAS (user_token.access_token) AND timestamp()/1000 < user_token.expiration_timestamp
OPTIONAL MATCH (user)-[:friends_with]-(friend:User)-[:is_authorized_by]->(friend_token:Token)
WHERE HAS (friend_token.access_token) AND timestamp()/1000 < friend_token.expiration_timestamp
RETURN user.id as userId, coalesce(user_token.access_token, friend_token.access_token) AS token
user.id IN ['123', '456']
is not yet an efficient operation. Only equality so far for index lookups – Michael HungerOPTIONAL MATCH (user)-[:is_authorized_by]->(user_token:Token)
Do you want one token per friend or only one friend-token in total? – Michael Hunger