neo4j中的传递关系

wyyhbhjk  于 2022-11-23  发布在  其他
关注(0)|答案(2)|浏览(255)

我刚刚开始使用neo4j。
我试图用它来描述一家公司的企业架构。
我想说明的是,通过删除节点“Middleware”,Service_A将从Client_A和Server_X中删除,其他服务也是如此。
有没有办法做到这一点?这是正确的方法吗?
接下来是用于生成图形的代码。

from neo4j import GraphDatabase
import logging
from neo4j.exceptions import ServiceUnavailable

class App:

    def __init__(self, uri, user, password):
        self.driver = GraphDatabase.driver(uri, auth=(user, password))

    def close(self):
        # Don't forget to close the driver connection when you are finished with it
        self.driver.close()

    def drop_everything(self):
        with self.driver.session(database="neo4j") as session:
            # Write transactions allow the driver to handle retries and transient errors
            session.execute_write(self._drop_everything)
            print("Graph DB dropped")

    @staticmethod
    def _drop_everything(tx):
        query = (
            "MATCH (n) DETACH DELETE (n)"
        )
        try:
            tx.run(query)

        # Capture any errors along with the query and data for traceability
        except ServiceUnavailable as exception:
            logging.error("{query} raised an error: \n {exception}".format(query=query, exception=exception))
            raise

    def create_system(self, system_name):
        with self.driver.session(database="neo4j") as session:
            # Write transactions allow the driver to handle retries and transient errors
            result = session.execute_write(self._create_system, system_name)
            print("Created system: {p1}".format(p1=result))

    @staticmethod
    def _create_system(tx, system_name):
        # To learn more about the Cypher syntax, see https://neo4j.com/docs/cypher-manual/current/
        # The Reference Card is also a good resource for keywords https://neo4j.com/docs/cypher-refcard/current/
        query = (
            "CREATE (n:system{name:$system_name}) "
            "RETURN (n)"
        )
        result = tx.run(query, system_name=system_name)
        try:
            return result.single()[0]["name"]
        # Capture any errors along with the query and data for traceability
        except ServiceUnavailable as exception:
            logging.error("{query} raised an error: \n {exception}".format(query=query, exception=exception))
            raise

    def create_flow(self, service_name_a, system1_name, system2_name):
        with self.driver.session(database="neo4j") as session:
            # Write transactions allow the driver to handle retries and transient errors
            result = session.execute_write(self._create_flow, service_name_a, system1_name, system2_name)
            print("Created flow: {p1}".format(p1=result))

    @staticmethod
    def _create_flow(tx, service_name, system1_name, system2_name):
        query = (
            "MATCH (p1:system), (p2:system) "
            "WHERE p1.name = '" + system1_name + "' AND p2.name = '" + system2_name +"' "
            "CREATE (p1)-[r:" + service_name + " {type:'call'}]->(p2) "
            "RETURN ('" + service_name + "')"
        )

        # CREATE (p1)-[r:service {name:'" + service_name + "'}]->(p2)
        # CALL apoc.create.relationship(p1, '$service_name', NULL, p2) YIELD rel
        # CREATE (p1)-[:service {name:'$service_name'}]->(p2) "

        result = tx.run(query, service_name=service_name, system1_name=system1_name, system2_name=system2_name)
        try:
            return service_name
        # Capture any errors along with the query and data for traceability
        except ServiceUnavailable as exception:
            logging.error("{query} raised an error: \n {exception}".format(query=query, exception=exception))
            raise

    def find_system(self, system_name):
        with self.driver.session(database="neo4j") as session:
            result = session.execute_read(self._find_system, system_name)
            for row in result:
                print("Found system: {row}".format(row=row))

    @staticmethod
    def find_system(tx, system_name):
        query = (
            "MATCH (p:system) "
            "WHERE p.name = $system_name "
            "RETURN p.name AS name"
        )
        result = tx.run(query, system_name=system_name)
        return [{ row["name"] } for row in result]

if __name__ == "__main__":
    # Aura queries use an encrypted connection using the "neo4j+s" URI scheme
    # https://console.neo4j.io/ - Login with google mario.stefanutti@gmail.com
    uri = "neo4j+s://8a9f54ab.databases.neo4j.io"
    user = "neo4j"
    password = "Xxx"
    app = App(uri, user, password)

    app.drop_everything()

    app.create_system("Client_A")
    app.create_system("Middleware")
    app.create_system("Server_X")
    app.create_system("Server_Y")
    app.create_system("Server_Z")

    app.create_flow("Service_A", "Client_A", "Middleware")
    app.create_flow("Service_B", "Client_A", "Middleware")
    app.create_flow("Service_C", "Client_A", "Middleware")

    app.create_flow("Service_A", "Middleware", "Server_X")
    app.create_flow("Service_B", "Middleware", "Server_Y")
    app.create_flow("Service_C", "Middleware", "Server_Z")

    app.close()
lvjbypge

lvjbypge1#

不同类型的节点是否有不同的标签?例如,客户端节点与服务器节点
如果要保留图形的当前结构,可以使用虚拟节点/关系概念折叠中间节点(即中间件),并在客户端和服务器之间创建(虚拟)关系。
请注意,虚拟关系将不存在于图形中,也不需要您删除中间件中介,但它将在UI层中用于可视化/表示。

MATCH (from:system)-[rel1:service]->(inter:system)-[rel2:service]->(to:system)
RETURN from, to, apoc.create.vRelationship(from,'SERVES', {}, to) as myVirtualRel;

看看https://neo4j.com/labs/apoc/4.1/virtual/virtual-nodes-rels/

ocebsuys

ocebsuys2#

对于此查询创建的图形(如图像中所示):

MERGE (c:Client)
MERGE (m:Middleware)
MERGE (s:Server_X)
MERGE (s1:Server_Y)
MERGE (s2:Server_Z)
MERGE (c)-[:SERVICE_A]->(m)-[:SERVICE_A]->(s)
MERGE (c)-[:SERVICE_B]->(m)-[:SERVICE_B]->(s1)
MERGE (c)-[:SERVICE_C]->(m)-[:SERVICE_C]->(s2)

此查询应该可以:

MATCH (c:Client)-[rel1]->(m:Middleware)-[rel2]->(server) WHERE type(rel1) = type(rel2)
MERGE (c)-[:CONNECTION]->(server)

相关问题