创建独特的关系,而不需要在neo4j中创建独特的节点 [英] Creating unique relationships without creating unique nodes in neo4j

查看:312
本文介绍了创建独特的关系,而不需要在neo4j中创建独特的节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我打破了一个问题,我问在别处到一个第二部分。

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

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



原来,我正在使用...

  fids = get_fids(record)#[100001,100002,100003,... etc] 
ids_in_my_graph = filter( (用户:用户:{{id_str:{}} { }})
RETURN用户
.format(id)
n = neo4j.CypherQuery(graph_db,query).execute_one()
如果n:
val = True
return(val)

for 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)

虽然我想要new / unique / [:朋友]的关系,如果一个节点没有,我不想创建新的用户或新的朋友已经存在一个有效的id_str。



所以,我想用集合的FOREACH来重写这个。我认为实际的语法是...

  MATCH(user:User {id_str:200001}),(friends :用户)
WHERE friends.id_str IN [100001,100002,100003,JUNK,DOESNTMATCH,IGNORED]
FOREACH(朋友中的朋友:
CREATE UNIQUE user - [:FRIENDS] - > friend)

但是我的错误是

  py2neo.neo4j.SyntaxException:无效输入'U':预期的空格,注释,NodeLabel,MapLiteral,参数,关系模式,' ','节点标签','','=',IN,IS,'*','/','%','^','+',' - ','<','> AND,XOR,OR或|(第3行,第48列)$ b $,=,> =,'=',< bFOREACH(朋友中的朋友:CREATE UNIQUE user  -  [:FRIENDS]  - > friend)

创建唯一似乎不被FOREACH构造支持,即使这个答案表明这个问题已经解决了。

再次,我不能使用在11.2.2中建议的语法 < a>,因为我不希望创建额外的节点,只有新的关系到已经存在的节点。 解决方案



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



,FOREACH里面的:分隔符已经改成|了,因为与用于类型和标签的:存在可读性冲突。

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



最后:

概念上,friends指向一个朋友一次,可以这么说,它不是所有的朋友的集合。你可以这样做:

$ p $ WITH user,COLLECT(friends)AS friends

  MATCH(用户:用户{id_str:200001}),(朋友:用户)
朋友.id_str IN [100001,100002,100003,JUNK,DOESNTMATCH,IGNORED]
MERGE(user) - [:FRIENDS] - > (朋友)

确保您在friend.id_str上定义了一个索引,否则这将非常慢:)

I am breaking out a question I asked elsewhere into a second part.

For a given node which has an id_str that is known to be in the graph, I have a list of new id_str that may or may not be in the graph. If they /are/ in the graph, I would like to create unique relationships to them. (If they are not, I want to ignore them.)

My current method is quite slow. I am doing the looping part outside of Neo, using py2neo and writing the entries one at a time using a very slow filter.

Originally, I was using...

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)

And while I want new /unique/ [:FRIENDS] relationships, I do not want to create new users or new friends if a node does not already exist with a valid id_str.

So, I am trying to rewrite this using the FOREACH with collections. I think the actual syntax would be...

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)

But my error is

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)"

Create Unique does not seem to be supported for the FOREACH construct, even though this answer suggests this has been fixed.

And again, I cannot use the syntax suggested here in 11.2.2 because I do not want additional nodes to be created, only new relationships to already-existing nodes.

解决方案

Couple of problems:

First, it will want parenthesises around the user and friend node in the CREATE UNIQUE pattern.

Second, the ":" separator inside FOREACH has been changed to "|", because there were readability clashes with the ":" used for types and labels.

Third, you should use MERGE instead of create unique. It's faster, more predictable and it replaces CREATE UNIQUE.

Finally:

Conceptually, the "friends" identifier points to one friend "at a time", so to speak, it isn't a collection of all the friends. You can turn it into such by doing:

WITH user, COLLECT(friends) AS friends

Of course, as you might've guessed, that actually means you don't need the FOREACH at all, so your final query could be:

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

Make sure you have an index defined on friend.id_str, otherwise this will be very slow :)

这篇关于创建独特的关系,而不需要在neo4j中创建独特的节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆