创建唯一关系而无需在neo4j中创建唯一节点

时间:2014-04-04 15:37:30

标签: foreach neo4j cypher py2neo

我正在向第二部分提出问题asked elsewhere

对于具有已知在图中的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)

虽然我想要新的/唯一的/ [:FRIENDS]关系,但如果一个节点不存在且有效的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)"
尽管this answer表明这已被修复,但

FOREACH构造似乎不支持创建唯一。

同样,我不能使用建议here in 11.2.2的语法,因为我不希望创建其他节点,只需要与已有节点建立新关系。

1 个答案:

答案 0 :(得分:2)

一些问题:

首先,它需要CREATE UNIQUE模式中用户和朋友节点周围的括号。

其次,FOREACH中的“:”分隔符已更改为“|”,因为存在与类型和标签使用的“:”的可读性冲突。

第三,你应该使用MERGE而不是create unique。它更快,更可预测,它取代了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上定义了一个索引,否则这将非常慢:)