使用 Neo4j Python 驱动程序时如何将 Label 设置为 cypher 查询中的变量

Hon*_* Bu 4 python neo4j

我试图将标签和关系设置为密码查询中的变量,因为我不想一一列出所有标签并为所有标签创建密码查询。

这就是我所做的:

class Neo4jClient(object):
    def __init__(self, uri, user, password):
        self._driver = GraphDatabase.driver(uri, auth=basic_auth(user, password))
    def close(self):
        self._driver.close()
    def merge_nodes_relationships(self, anchor_data):
        event = anchor_data.event
        anchor = anchor_data.anchor
        for k, v in anchor.items():
            relation = session.write_transaction(self.create_event_anchor_relation, event, k, v)
    @staticmethod
    def create_event_anchor_relation(tx, event, anchorkey, anchorvalue):
        result =  tx.run("MATCH(e: Event {id : $eventid}), (a: $Anchor {id:$anchorvalue)"
                         "MERGE(e)-[r:$RelationShip]-(a)"
                         "RETURN r", eventid=event['id'], Anchor=anchorkey, anchorvalue=anchorvalue, RelationShip='EVENT_' + anchorkey
                         )
        return result.single()[0]
Run Code Online (Sandbox Code Playgroud)

但错误抛出说

输入“$”无效:预期的空格或标签名称(第 1 行,第 10 列(偏移量:9))\n\"MERGE (a:$Anchor {id : $id})\"\n

那么我应该如何解决这个问题呢?如果不支持参数化标签或关系,当出现许多具有相同属性但需要不同标签名称的标签时,处理这种情况的最佳实践是什么。

Joe*_*ick 5

通常应该避免这种情况,但以下方法会起作用:

MATCH (e :Event {id: $eventid}), (a {id: $anchorvalue)
WHERE $Anchor IN LABELS(a)
MERGE(e)-[r]-(a)
WHERE $RelationShip IN LABELS(r)
RETURN r
Run Code Online (Sandbox Code Playgroud)

编辑:要了解为什么这是不好的,请运行以下两个查询:

PROFILE
MATCH (e :Event)
RETURN e
Run Code Online (Sandbox Code Playgroud)

PROFILE
MATCH (e)
WHERE "Event" IN LABELS(e)
RETURN e
Run Code Online (Sandbox Code Playgroud)

请注意,它们实际上返回相同的内容,但它们以非常不同的方式执行。

第一个运行NodeByLabelScan快速查找带有标签“Event”的所有节点。由于 Neo4j 存储这些数据的方式,这些节点“存储在一起”并且查找起来非常快。

运行第二个查询AllNodesScan,然后运行Filter​​. 通过这种方式,必须检查数据库中的每个节点以查看其是否具有“事件”作为标签。

一般来说,如果您使用标签作为变量,则说明您没有为数据选择非常好的结构。