2014-04-04 67 views
1

我将第列为第二部分。在neo4j中创建唯一关系而不创建唯一节点

对于一个已知id_str已知在图中的给定节点,我有一个新的id_str列表,这些列表可能包含或不包含在图中。如果他们/在图中,我想与他们建立独特的关系。 (如果它们不是,我想忽略它们)。

我现在的方法很慢。我正在做Neo之外的循环部分,使用py2neo并使用非常慢的过滤器逐个写入条目。

本来,我是用...

fids = get_fids(record) # [100001, 100002, 100003, ... etc] 
ids_in_my_graph = filter(id_is_in_graph, fids) # [100002] 

def id_is_in_graph(id): 
    val = False 
    query = """MATCH (user:User {{id_str:"{}"}}) 
    RETURN user 
    """.format(id) 
    n=neo4j.CypherQuery(graph_db,query).execute_one() 
    if n: 
     val = True 
    return(val) 

for i in ids_in_my_graph: 
    """MATCH (user:User {{id_str:"{}"}}),(friend:User {{id_str:"{}"}}) 
     WHERE has(user.id_str) AND has(friend.id_str) 
     CREATE UNIQUE (user)-[:FRIENDS]->(friend)""".format(record.id, i) 

虽然我希望新的/独特/ [:朋友]的关系,我不希望创建新的用户或者新朋友如果一个节点已经不存在一个有效的id_str。

所以,我试图用集合中的FOREACH来重写这个。我认为实际的语法会...

MATCH (user:User {id_str:"200001"}), (friends:User) 
WHERE friends.id_str IN ["100001", "100002", "100003", "JUNK", "DOESNTMATCH", "IGNORED"] 
FOREACH(friend in friends : 
CREATE UNIQUE user -[:FRIENDS]-> friend) 

但我的错误是

py2neo.neo4j.SyntaxException: Invalid input 'U': expected whitespace, comment, NodeLabel, MapLiteral, a parameter, a relationship pattern, '.', node labels, '[', "=~", IN, IS, '*', '/', '%', '^', '+', '-', '<', '>', "<=", ">=", '=', "<>", "!=", AND, XOR, OR or '|' (line 3, column 48) 
"   FOREACH(friend in friends : CREATE UNIQUE user -[:FRIENDS]-> friend)" 

创造出独特的似乎并不被支持foreach构造,即使this answer表明,这已得到修复。

再次,我不能使用语法建议here in 11.2.2,因为我不想要创建额外的节点,只有与已有节点的新关系。

回答

2

两个问题:

首先,将要围绕在CREATE独特的模式在用户与朋友节点parenthesises。其次,FOREACH内部的“:”分隔符已被更改为“|”,因为与用于类型和标签的“:”存在可读性冲突。

第三,您应该使用MERGE而不是创建唯一的。它更快,更可预测,它取代了CREATE UNIQUE。

最后:

从概念上讲,“朋友”标识符指向一个朋友“在同一时间”,可以这么说,它是不是所有的朋友的集合。您可以通过把它变成这样:

WITH user, COLLECT(friends) AS friends 

当然,你可能已经猜到,这实际上意味着你不需要在foreach可言,所以你的最终查询可能是:

MATCH (user:User {id_str:"200001"}), (friend:User) 
WHERE friend.id_str IN ["100001", "100002", "100003", "JUNK", "DOESNTMATCH", "IGNORED"] 
MERGE (user) -[:FRIENDS]-> (friend) 

确保你有一个在friend.id_str上定义的索引,否则这将会非常缓慢:)

+0

MERGE是否保持关系的唯一性?如果我运行两次,我不会在(a)和(b)之间获得第二个[:FRIENDS]关系? – Mittenchops

+0

不,这正是我不想要的 - 它创造了图中不存在的新(朋友)。该死。=( – Mittenchops

+0

其实,它做了2件不可取的事情,它创建了一个新的(朋友),它也只做了1个连接,而不是朋友中每个朋友的连接,所以我不认为朋友标识符的行为如你所说。合并的结果是(用户)和一个新创建的(朋友)之间的单个连接,这个连接不在图中,而不是1(用户)连接到已经在图中的已知X(朋友)。 – Mittenchops