You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
3.7 KiB
133 lines
3.7 KiB
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
# @Time : 2023/4/15 11:05
|
|
# @Author : old tom
|
|
# @File : graph_helper.py
|
|
# @Project : futool-tiny-datahub
|
|
# @Desc : 血缘关系上图,关系查询
|
|
from py2neo import Node, Relationship, Graph, Subgraph
|
|
from py2neo.matching import NodeMatcher
|
|
|
|
|
|
class Neo4jHelper(object):
|
|
def __init__(self, graph: Graph):
|
|
self.graph = graph
|
|
self.node_matcher = NodeMatcher(graph)
|
|
|
|
def find_node(self, *labels, **properties):
|
|
"""
|
|
查找节点
|
|
:param labels:
|
|
:param properties:
|
|
:return: 可能有多个
|
|
"""
|
|
rt = self.node_matcher.match(*labels, **properties)
|
|
return rt
|
|
|
|
def find_node_by_id(self, node_id):
|
|
"""
|
|
节点ID 查找节点
|
|
:param node_id:
|
|
:return:
|
|
"""
|
|
return self.node_matcher.get(node_id)
|
|
|
|
def check_node_exists(self, *labels, **properties):
|
|
"""
|
|
判断节点是否存在
|
|
:param labels:
|
|
:param properties:
|
|
:return:
|
|
"""
|
|
return self.find_node(*labels, **properties).exists()
|
|
|
|
def same_node_count(self, *labels, **properties):
|
|
"""
|
|
相同节点数
|
|
:param labels:
|
|
:param properties:
|
|
:return:
|
|
"""
|
|
return self.find_node(labels, properties).count()
|
|
|
|
def find_same_node(self, *labels, **properties):
|
|
"""
|
|
查找相同节点
|
|
:param labels:
|
|
:param properties:
|
|
:return:
|
|
"""
|
|
return self.find_node(*labels, **properties).all()
|
|
|
|
def merge_subgraph(self, relationship, label, *property_keys):
|
|
"""
|
|
合并子图
|
|
:param property_keys: 判断节点重复属性
|
|
:param label: 节点标签
|
|
:param relationship:
|
|
:return:
|
|
"""
|
|
self.graph.merge(relationship, label, *property_keys)
|
|
|
|
def find_subgraph(self):
|
|
pass
|
|
|
|
def create_subgraph(self, nodes: list, edges: list):
|
|
"""
|
|
创建子图,注:相同节点不会自动去重
|
|
:param nodes: 节点列表
|
|
:param edges: 边(关系列表)
|
|
:return:
|
|
"""
|
|
# 开启事务
|
|
tx = self.graph.begin()
|
|
try:
|
|
tx.create(Subgraph(nodes=nodes, relationships=edges))
|
|
self.graph.commit(tx)
|
|
except Exception as e:
|
|
self.graph.rollback(tx)
|
|
|
|
def create_node(self, *labels, **properties):
|
|
"""
|
|
创建节点
|
|
:param node:
|
|
:return:
|
|
"""
|
|
node = Node(*labels, **properties)
|
|
self.graph.create(node)
|
|
return node
|
|
|
|
def create_node_with_check(self, *labels, **properties):
|
|
"""
|
|
创建节点前判断是否存在
|
|
:param labels:
|
|
:param properties:
|
|
:return: 创建的节点或已经存在的节点
|
|
"""
|
|
if not self.check_node_exists(*labels, **properties):
|
|
return self.create_node(*labels, **properties)
|
|
return self.find_node(*labels, **properties).first()
|
|
|
|
def create_relationship(self, from_node, relation_desc, to_node):
|
|
"""
|
|
创建关系
|
|
:param to_node:
|
|
:param relation_desc: 关系描述
|
|
:param from_node:
|
|
:return:
|
|
"""
|
|
self.graph.create(Relationship(from_node, relation_desc, to_node))
|
|
|
|
def create_relationship_with_merge(self, from_node, relation_desc, to_node, label, *property_keys):
|
|
"""
|
|
创建关系并合并相同节点
|
|
:param label: 标签
|
|
:param from_node:
|
|
:param relation_desc: 关系描述
|
|
:param to_node:
|
|
:return:
|
|
"""
|
|
relation = Relationship(from_node, relation_desc, to_node)
|
|
self.graph.create(relation)
|
|
self.merge_subgraph(relation, label, *property_keys)
|