查询确切数量的关系

时间:2016-06-03 22:10:19

标签: neo4j cypher

我正在尝试找出适当的群组聊天Cypher查询,我已建模如下:

(u:user)-[:in_conversation]->(c:conversation)
(c:conversation)-[:has_message]->(m:message)

因此,如果3个用户正在进行对话,我将有3个用户具有in_conversation关系。

为特定人员列表查找或创建对话的最佳方式是什么

例如,我可能会在userA和userB之间进行对话,但会在userA,userB和userC之间进行对话。

因此,如果我想抓住userA-userB会话,我不想因为它具有正确的关系而意外地抓住userA-userB-userC会话。

2 个答案:

答案 0 :(得分:1)

有几种方法可以做到这一点。我建议匹配userAuserB所涉及的所有会话,并确保这些会话恰好有两个in_conversation关系(即A和B)。然后你确定没有其他人参与其中:

MATCH (:user{name:'UserA'})-[:in_conversation]->(c:conversation)<-[:in_conversation]-(:user{name:'UserB'})
WITH c, size( (c)<-[:in_conversation]-() ) as count
WHERE count = 2
RETURN c

答案 1 :(得分:1)

1)找对话:

// Get a list of users (create if no such people)
//
UNWIND ['A','B','C'] AS participantName MERGE (U:User {name: participantName})

// Sorting is necessary for future comparison
//
WITH U ORDER BY ID(U)
WITH COLLECT(DISTINCT U) as conversationParticipants

// It is enough to check to find all the conversation of one user
// to check the coincidence of at least one
//
OPTIONAL MATCH (U:User)-[:in_conversation]->(C:Conversation) 
    WHERE ID(U) = ID(HEAD(conversationParticipants))  
OPTIONAL MATCH (inU:User)-[:in_conversation]->(C)

    // Sorting is necessary for future comparison
    //
    WITH conversationParticipants, C, inU ORDER BY ID(inU)
    WITH conversationParticipants, C, collect(distinct inU) as tmp

// Take one conversation in which there is a match 
// with the initial user list
//
WITH conversationParticipants, HEAD(FILTER(c in COLLECT({c:C,tmp:tmp}) 
    WHERE  conversationParticipants = c['tmp']) )['c'] as conversation
RETURN conversationParticipants, conversation

2)创建对话(需要apoc来创建uuid):

UNWIND ['A','B','C'] AS participantName MERGE (U:User {name: participantName})
WITH U ORDER BY ID(U)
WITH COLLECT(DISTINCT U) as conversationParticipants
OPTIONAL MATCH (U:User)-[:in_conversation]->(C:Conversation) 
    WHERE ID(U) = ID(HEAD(conversationParticipants))  
OPTIONAL MATCH (inU:User)-[:in_conversation]->(C)
    WITH conversationParticipants, C, inU ORDER BY ID(inU)
    WITH conversationParticipants, C, collect(distinct inU) as tmp
WITH conversationParticipants, HEAD(FILTER(c in COLLECT({c:C,tmp:tmp}) 
    WHERE  conversationParticipants = c['tmp']) )['c'] as conversation

// Use apoc.create.uuid to generate UUID
//
CALL apoc.create.uuid() YIELD uuid as tmpUUID

// Check if conversation not exist
//
WITH conversationParticipants, conversation.uuid as ifexist, 
     COALESCE( conversation.uuid, tmpUUID ) as uuid
MERGE (C:Conversation {uuid: uuid})

// Create :in_converstation relationship
//
FOREACH (x IN CASE ifexist WHEN NULL THEN [1] ELSE [] END |
  FOREACH (user IN conversationParticipants |
    MERGE (user)-[:in_conversation]->(C)
  )
)
RETURN conversationParticipants, C as conversation