限制Neo4j Cypher中的匹配数量

时间:2014-05-04 06:33:22

标签: neo4j cypher

我有以下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

3 个答案:

答案 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