限制Neo4j Cypher中的匹配数

限制Neo4j Cypher中的匹配数,neo4j,cypher,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 对于每个用户,我需要获取其令牌(如果它有有效的令牌)或有效朋友的令牌 我编写了以下密码查询: MATCH (user:User) W

我有以下Neo4j场景(我使用的是Neo4j 2.0.1):

节点:

User
Token
关系:

friends_with -> bidirectional relationship between Users
is_authorized_by -> directed relationship between a User and a Token
对于每个用户,我需要获取其令牌(如果它有有效的令牌)或有效朋友的令牌

我编写了以下密码查询:

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
匹配(user:user),其中user.id位于['123','456']
可选匹配(用户)-[:由用户授权]->(用户令牌:令牌)
其中有(user\u token.access\u token)和timestamp()/1000(朋友令牌:令牌)
其中有(friend_token.access_token)和timestamp()/1000
当然,这不起作用,因为第二个可选匹配项不仅匹配第一个朋友的令牌

我想做的是:

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
匹配(user:user),其中user.id位于['123','456']
可选匹配(用户)-[:由用户授权]->(用户令牌:令牌)
其中有(user\u token.access\u token)和timestamp()/1000(朋友令牌:令牌)
其中HAS(friend\u token.access\u token)和timestamp()/1000(朋友令牌:令牌)
其中有(friend_token.access_token)和timestamp()/1000
要仅返回返回列表中的任何一个,您可以应用MAX之类的聚合函数,即

将user.id返回为userId,MAX(coalesce(user\u token.access\u token, 朋友(令牌。访问(令牌))作为令牌

由于
coalesce()
函数已最多返回一个
access\u令牌
,因此您只需为每个
用户ID返回一行即可:

RETURN DISTINCT user.id as userId, coalesce(user_token.access_token, friend_token.access_token) AS 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
MATCH(用户:用户{id:'123})
对于用户,头(过滤器(令牌输入
提取(用户中的p)-[:被授权者]->(:令牌)|最后一个(节点(p)))
其中token.access_token和timestamp()/1000(:令牌)|最后一个(节点(p)))
其中token.access_token和timestamp()/1000
这是一个可能的解决方案,但我担心查询可能会遍历整个图形。是这样吗?它只是遍历用户朋友,而不是整个图。观察得好,我应该只查找直接朋友的标记。但你有什么建议:1。为每个用户运行查询,并使用WITH和LIMIT或2。为多个用户运行此查询,希望遍历所有好友会导致性能损失?您能重新表述您的问题吗?我不明白确切的意思。运行--
MATCH(user:user)WHERE user.id='123'可选匹配(user)-[:is\u authorized\u by]->(user\u token:token)WHERE HAS(user\u token.access\u token)和timestamp()/1000(friends\u token:token:token)WHERE HAS HAS(friend_token.access_token)和timestamp()/1000
--应该在第一个friend_token匹配后停止,对吗?在查询上运行配置文件似乎表明这也是在应用“DISTINCT”之前首先遍历图形的。是否有可能在发现第一个好友_令牌时实际停止此操作?@user3455402如果用户有更多具有有效令牌的好友,此查询即使具有distinct,也会为每个不同的好友返回一行token@remigio正确的观点!只是出于好奇,有没有办法指定每列的独立性?我不确定在这一点上,你能举一个每列不同的例子吗?请注意,['123','456']
中的
user.id还不是一个有效的操作。到目前为止,索引查找只返回相等的行数。这个返回的行数是多少?你想把它也限制为一行吗?
可选匹配(用户)-[:is\u authorized\u by]>(用户令牌:token)
您希望每个朋友有一个令牌还是总共只有一个令牌?@MichaelHunger用户总是只有一个令牌。我可以使用用户自己的令牌或直接朋友的令牌来授权用户。最后,我希望为每个用户返回一个有效令牌,而不是用户自己的令牌。这似乎接近我需要的。用户ways只有一个令牌。我可以使用用户自己的令牌或直接朋友的令牌对用户进行授权。最后,我希望为每个用户返回一个有效令牌,而不是用户自己的令牌。令牌之间没有关联。我需要返回“用户ID”-“有效访问令牌”对。在您的情况下,我只想返回“123”-“123的有效令牌”。在我最初的场景中,我搜索了ID为“123”和“456”的两个用户,所以我想返回两行:“123”-“123的有效令牌”和“45”
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