我有以下Neo4j场景(我正在使用Neo4j 2.0.1):
节点:
User
Token
关系:
friends_with -> bidirectional relationship between Users
is_authorized_by -> directed relationship between a User and a Token
对于每个用户,我需要获得其令牌(如果它具有有效的令牌)或有效的朋友的令牌。
我写了以下Cypher查询:
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
当然,这不起作用,因为第二个OPTIONAL MATCH不仅匹配第一个朋友的令牌。
我想做的是:
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
如何实现这一目标?
修改1:
我只对直接朋友的代币感兴趣:
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
答案 0 :(得分:1)
要从返回的列表中返回任何一个,您可以应用MAX等聚合函数,即
将user.id作为userId,MAX返回(合并(user_token.access_token, friend_token.access_token))AS令牌
答案 1 :(得分:0)
由于coalesce()
函数最多只返回一个access_token
,因此您只想每userId
返回一行:
RETURN DISTINCT user.id as userId, coalesce(user_token.access_token, friend_token.access_token) AS token
答案 2 :(得分:0)
这会返回多少行?你想把它限制在一个吗?
OPTIONAL MATCH (user)-[:is_authorized_by]->(user_token:Token)
你想要每个朋友一个令牌还是只需要一个朋友令牌?
您的令牌似乎也没有连接?所以你可能也想要做这样的事情?只是猜测,不确定这是否会像你一样表现。
MATCH (user:User {id:'123'})
WITH user, head(filter(token in
extract(p in (user)-[:is_authorized_by]->(:Token) | last(nodes(p)))
WHERE token.access_token AND timestamp()/1000 < token.expiration_timestamp)) as user_token
OPTIONAL MATCH (user)-[:friends_with*1..3]-(friend:User)
WITH user, user_token,
head(filter(token in
extract(p in (friend)-[:is_authorized_by]->(:Token) | last(nodes(p)))
WHERE token.access_token AND timestamp()/1000 < token.expiration_timestamp)) as friend_token
RETURN user.id as userId, coalesce(user_token.access_token, friend_token.access_token) AS token