当前位置: 首页 > news >正文

neo4j 图表数据导入到 TuGraph

neo4j 图表数据导入到 TuGraph

  • 代码文件
    • 说明
    • 后文

前言:近期在引入阿里的 TuGraph 图数据库,需要将 原 neo4j 数据导入到新的 tugraph 数据库中。预期走csv文件导入导出,但因为格式和数据库设计问题,操作起来比较麻烦(可能是个人没有发现其他比较方便的办法),因此写了一个 python 脚本进行数据导入操作。

使用:python3,TuGraph 4.5.1

遇到的问题:tugraph 的节点需要一个主键,这个只能自行指定。

支持:指定节点,指定边。自动创建不存在的节点/边,数据导入批量导入节点,单条导入边(试过批量的,tugraph好像不支持 官网的 CALL db.upsertEdge 我的版本也还没实现)。

导入图示:在这里插入图片描述

在这里插入图片描述

代码文件

# import time
import json
from typing import Dict, List, castclass GraphConnector():db_type: str = "tugraph"driver: str = "bolt"dialect: str = "cypher"batch_size: int = 100# 指定节点的主键node_pro_key: dict = dict({'Ren':'zjhm','Aj':'ajbh','Che':'rowkey','Hh':'rowkey','Sj':'dhhm'})#指定需要导入的边specified_relation = ['ajgx','th','tfj','sysj','sycl']#指定需要导入的节点specified_node = ['Ren','Aj','Che','Sj','Hh']def __init__(self, driver, graph):"""Initialize the connector with a Neo4j driver."""self._driver = driverself._schema = Noneself._graph = graphself._session = None@classmethoddef from_uri_db(cls, host: str, port: int, user: str, pwd: str, db_name: str, db_type: str) -> "GraphConnector":"""Create a new TuGraphConnector from host, port, user, pwd, db_name."""try:from neo4j import GraphDatabasecls.db_type = db_typedb_url = f"{cls.driver}://{host}:{str(port)}"driver = GraphDatabase.driver(db_url, auth=(user, pwd))driver.verify_connectivity()return cast(GraphConnector, cls(driver=driver, graph=db_name))except ImportError as err:raise ImportError("neo4j package is not installed, please install it with ""`pip install neo4j`") from errdef create_graph_new(self, graph_name: str) -> bool:"""Create a new graph in the database if it doesn't already exist."""try:with self._driver.session() as session:graph_list = session.run("CALL dbms.graph.listGraphs()").data()exists = any(item["graph_name"] == graph_name for item in graph_list)if not exists:session.run(f"CALL dbms.graph.createGraph('{graph_name}', '', 2048)")except Exception as e:raise Exception(f"Failed to create graph '{graph_name}': {str(e)}") from ereturn not existsdef create_vertex_labels(self, json_data):try:with self._driver.session(database=self._graph) as session:# graph_list = session.run(f"CALL db.createVertexLabelByJson({json_data})").data()session.run("CALL db.createVertexLabelByJson($json_data)",json_data=json_data)except Exception as e:raise Exception(f"Failed to create vertex_labels ") from e# 批量更新节点,没有就新增,有就更新def batch_update_node(self, json_data):try:with self._driver.session(database=self._graph) as session:# graph_list = session.run(f"CALL db.createVertexLabelByJson({json_data})").data()session.upsertVertex("CALL db.upsertVertex($json_data)",json_data=json_data)except Exception as e:raise Exception(f"Failed to create vertex_labels ") from e# 批量更新关系,没有就新增,有就更新def batch_update_edge(self, json_data):try:with self._driver.session(database=self._graph) as session:# graph_list = session.run(f"CALL db.createVertexLabelByJson({json_data})").data()session.upsertVertex("CALL db.upsertEdge($json_data)",json_data=json_data)except Exception as e:raise Exception(f"Failed to create vertex_labels ") from edef create_edge_labels(self, json_data):try:with self._driver.session(database=self._graph) as session:# graph_list = session.run(f"CALL db.createVertexLabelByJson({json_data})").data()session.run("CALL db.createEdgeLabelByJson($json_data)",json_data=json_data)except Exception as e:raise Exception(f"Failed to create vertex_labels ") from edef run(self, query: str, fetch: str = "all") -> List:"""Run query."""with self._driver.session(database=self._graph) as session:try:result = session.run(query)return list(result)except Exception as e:raise Exception(f"Query execution failed: {e}\nQuery: {query}") from edef check_label_exists(self, label: str, label_type: str) -> bool:with self._driver.session(database=self._graph) as session:# Run the query to get vertex labelsif label_type == "node":raw_vertex_labels = session.run("CALL db.vertexLabels()").data()vertex_labels = [table_name["label"] for table_name in raw_vertex_labels]if label in vertex_labels:return Trueelse:# Run the query to get edge labelsraw_edge_labels = session.run("CALL db.edgeLabels()").data()edge_labels = [table_name["label"] for table_name in raw_edge_labels]if label in edge_labels:return Truereturn False# 获取节点或边的结构def get_columns(self, table_name: str, table_type: str = "vertex") -> List[Dict]:"""Retrieve the column for a specified vertex or edge table in the graph db."""with self._driver.session(database=self._graph) as session:data = []result = Noneif table_type == "vertex":result = session.run(f"CALL db.getVertexSchema('{table_name}')").data()else:result = session.run(f"CALL db.getEdgeSchema('{table_name}')").data()schema_info = json.loads(result[0]["schema"])for prop in schema_info.get("properties", []):prop_dict = {"name": prop["name"],"type": prop["type"],"default_expression": "","is_in_primary_key": bool("primary" in schema_infoand prop["name"] == schema_info["primary"]),"comment": prop["name"],}data.append(prop_dict)return datadef close(self):"""Close the Neo4j driver."""self._driver.close()# {"name": "id", "type": "STRING", "optional": False},
# {"name": "name", "type": "STRING", "optional": False, "index": True},
# {"name": "num", "type": "STRING", "optional": False, "unique": True},
# {"name": "desc", "type": "STRING", "optional": True}
# 构建节点json语句用于tugraph创建节点
def bulid_node_json(node_name:str,pro_key:str ,node_properties):vertex_label_json = {"label": node_name,"primary": pro_key,"type": "VERTEX","detach_property": True,"properties": []}for node_property in node_properties:proper_info = {"name": node_property[0], "type": "STRING", "optional": False}vertex_label_json['properties'].append(proper_info)return json.dumps(vertex_label_json)def bulid_edge_json(edge_name:str,edge_properties,start_node_key,end_node_key):edge_label_json = {"label": edge_name,"type": "EDGE","detach_property": True,"constraints": [],"properties": []}edge_label_json['constraints'].append([edge_properties[0][1][0],edge_properties[0][2][0]])# 这是在边属性中存储节点的主键(不需要也可以)# edge_label_json['properties'].append({"name": start_node_key if start_node_key != end_node_key else start_node_key+'1', "type": "STRING", "optional": False})# edge_label_json['properties'].append({"name": end_node_key if start_node_key != end_node_key else start_node_key+'2', "type": "STRING", "optional": False})for edge_property in edge_properties:proper_info = {"name": edge_property[0], "type": "STRING", "optional": True}edge_label_json['properties'].append(proper_info)return json.dumps(edge_label_json)def neo4jNode2Tugrapg(connector,tugraphConn):query = """CALL db.labels() YIELD labelRETURN label;"""print("Executing query:", query)results_nodes = connector.run(query)print(f"所有的节点:{results_nodes}")print("指定的节点:",connector.specified_node)for node in results_nodes:#获取节点结构query = f"""MATCH (n:{node[0]})UNWIND keys(n) AS keyRETURN DISTINCT key"""node_properties = connector.run(query)if node[0] not in connector.specified_node and len(connector.specified_node) != 0:continueprint(f"当前 neo4j 节点 {node[0]} , roperties : {node_properties}!!")if tugraphConn.check_label_exists(node[0],"node"):print(node[0],"节点已经存在!")else:print(node[0],"节点不存在,需要新建!")node_json = bulid_node_json(node[0],connector.node_pro_key[node[0]],node_properties)# 新建不存在的节点tugraphConn.create_vertex_labels(node_json)# neo4j中查询出当前节点标签下所有节点queryNode = f"MATCH (n:{node[0]}) RETURN n"# 构建插入语句同步节点synchronize_node(node[0],connector.run(queryNode),node_properties,tugraphConn)# node_name 当前节点标签名
# node_result neo4j中查询出的节点结果
# tugraphConn tugraph连接器
# 构建新增节点语句并tugraphConn 执行,一次执行300条
#  CREATE (:node1 {id: "2", name: "李四", num: "001", desc: "李四的信息"}),
#        (:node1 {id: "3", name: "李四", num: "001", desc: "李四的信息"});
def synchronize_node(node_name:str,node_result,node_properties,tugraphConn):# 构建Cypher查询语句print(f"同步 {node_name} 节点共 {len(node_result)} 记录,请等待执行完成...")create_node_cypher_parts = []count = 0skip_num = 0for node in node_result:# print("aa",aa)item = node[0]._propertiesproperties_list = []is_skip = Falsefor key in node_properties:# 如果节点结构与当前节点属性结构不一致,则跳过当前节点if key[0] not in item.keys():skip_num += 1is_skip = Truebreakif is_skip:continuefor key, value in item.items():properties_list.append(f"{key}: '{value}'")# if isinstance(value, str):#     # 如果是字符串,则添加引号#     properties_list.append(f"{key}: '{value}'")# else:#     # 否则直接添加#     properties_list.append(f"{key}: {value}")cypher_query = f"(:{node_name} {{{', '.join(properties_list)}}})"create_node_cypher_parts.append(cypher_query)count += 1# 每300个节点执行一次TuGraph数据库操作if count % 300 == 0:create_node_cypher = f"CREATE {', '.join(create_node_cypher_parts)}"# print(create_node_cypher)  # 打印生成的Cypher查询语句以便调试tugraphConn.run(create_node_cypher)create_node_cypher_parts = []  # 清空列表以准备下一批节点# 处理剩余的节点if create_node_cypher_parts:create_node_cypher = f"CREATE {', '.join(create_node_cypher_parts)}"# print(create_node_cypher)  # 打印生成的Cypher查询语句以便调试tugraphConn.run(create_node_cypher)print(f"所有 {node_name} 节点同步完成,共 {len(node_result)} 条记录,不符合要求 {skip_num} 条;成功导入 {count} 条!")# 导入边
def neo4jEdge2Tugrapg(connector,tugraphConn):query = """CALL db.relationshipTypes() YIELD relationshipTypeRETURN relationshipType;"""print("Executing query:", query)results_dege = connector.run(query)print(f"所有的关系:{results_dege}")print(f"指定的关系:{connector.specified_relation}")for edge in results_dege:if edge[0] not in connector.specified_relation and len(connector.specified_relation) != 0:continue#   获取关系结构query = f"""MATCH (n1)-[r:{edge[0]}]->(n2) UNWIND keys(r) AS key RETURN DISTINCT key, labels(n1) AS start_node_labels, labels(n2) AS end_node_labels"""edge_properties = connector.run(query)start_node = edge_properties[0][1][0]end_node = edge_properties[0][2][0]if start_node not in connector.specified_node or end_node not in connector.specified_node:print(f"{edge[0]}关系中存在不符合要求的节点,跳过!")continueif tugraphConn.check_label_exists(edge[0],"edge"):print(edge[0],"关系已经存在!")else:print(edge[0],"关系不存在,需要新建!")#获取节点结构node_json = bulid_edge_json(edge[0],edge_properties, connector.node_pro_key[start_node], connector.node_pro_key[end_node])# 新建不存在的节点tugraphConn.create_edge_labels(node_json)# neo4j中查询出当前节点标签下所有节点queryNode = f"MATCH (n1)-[r:{edge[0]}]->(n2) RETURN n1,r,n2;"results = connector.run(queryNode)# 构建插入语句同步节点synchronize_edge(edge[0],results,start_node,end_node,tugraphConn)def synchronize_edge(edge_name:str,edge_results,start_node_name,end_node_name,tugraphConn):# 构建Cypher查询语句print(f"同步 {edge_name} 关系共 {len(edge_results)} 记录,请等待执行完成...")create_node_cypher_parts = []count = 0skip_num = 0for edge in edge_results:properties_list = []for gx in edge:if hasattr(gx, 'type'):if list(gx.start_node.labels)[0] == start_node_name and list(gx.end_node.labels)[0] == end_node_name:start_node = gx.start_nodeend_node = gx.end_nodestart_pro_key = tugraphConn.node_pro_key[start_node_name]end_pro_key = tugraphConn.node_pro_key[end_node_name]start_pro_val = start_node[start_pro_key]end_pro_val = end_node[end_pro_key]# 创建一个字典来存储所有属性csv_map = {# start_pro_key if start_node_name != end_node_name else start_pro_key+'1': start_pro_val,# end_pro_key if start_node_name != end_node_name else end_pro_key+'2': end_pro_val}csv_map.update(gx)# 将属性字典转换为 JSON 风格的字符串# 构造关系属性字符串rel_props_list = [f"{key}: '{value}'" for key, value in csv_map.items()]rel_props_str = "{ " + ", ".join(rel_props_list) + " }"# todo 批量操作存储属性的# str1 = f"{{startId:'{start_pro_val}', endId:'{end_pro_val}', relProps:{rel_props_str}}}"# properties_list.append(str1)# create_node_cypher_parts.append(str1)create_edge_cypher = f"""MATCH (n1:{start_node_name} {{{start_pro_key}: '{start_pro_val}'}}),(n2:{end_node_name} {{{end_pro_key}: '{end_pro_val}'}})CREATE (n1)-[:{edge_name} {rel_props_str}]->(n2);"""# print(f"执行新增关系[{edge_name}]的cypher:{create_edge_cypher}")tugraphConn.run(create_edge_cypher)count += 1else:break#         批量操作 (tugraph不支持)#     if count % 3 == 0 and create_node_cypher_parts:#         map = {##         }#         queue_cypher = f"""#             UNWIND [{', '.join(create_node_cypher_parts)}] AS relData#             MATCH (a:{start_node_name} {{{tugraphConn.node_pro_key[start_node_name]}: relData.startId}}), (b:{end_node_name} {{{tugraphConn.node_pro_key[end_node_name]}: relData.endId}})#             MERGE (a)-[r:{edge_name}]->(b)#             SET r += relData.relProps#             RETURN r;#         """#         print(f"执行新增关系[{edge_name}]的cypher:{queue_cypher}")#         # tugraphConn.run(queue_cypher)#         create_node_cypher_parts = []# if create_node_cypher_parts:#     queue_cypher = f"""#             UNWIND [{', '.join(create_node_cypher_parts)}] AS relData#             MATCH (a:{start_node_name} {{{tugraphConn.node_pro_key[start_node_name]}: relData.startId}}), (b:{end_node_name} {{{tugraphConn.node_pro_key[end_node_name]}: relData.endId}})#             MERGE (a)-[r:{edge_name}]->(b)#             SET r += relData.relProps#             RETURN r;#         """#     print(f"执行新增关系[{edge_name}]的cypher:{queue_cypher}")# tugraphConn.run(queue_cypher)print(f"所有 {edge_name} 节点同步完成,共 {len(edge_results)} 条记录,不符合要求 {skip_num} 条;成功导入 {count} 条!")# 创建连接器
def conn_tugraph():# 配置连接信息host = "1111"port = 111user = "111"password = "111"db_name = "test121"db_type = "tugraph"connector = GraphConnector.from_uri_db(host, port, user, password, db_name, db_type)return connector
def conn_neo4j():# 配置连接信息host = "11111"port = 111user = "111"password = "111111"db_name = "111"db_type = "neo4j"connector = GraphConnector.from_uri_db(host, port, user, password, db_name, db_type)return connectordef main():neo4jConn = conn_neo4j()tugraphConn = conn_tugraph()print("Successfully connected to Graph!")# 创建TuGraph新图库 - 连接时选中,可以手动创建,或者在初始化方法中创建tugraphConn.create_graph_new("test121")# 导入节点neo4jNode2Tugrapg(neo4jConn,tugraphConn)# 导入边neo4jEdge2Tugrapg(neo4jConn,tugraphConn)# get_relation_tocsv(connector)# 关闭连接neo4jConn.close()tugraphConn.close()print("Connection closed.")if __name__ == "__main__":main()

说明

只是用Python简单写了一个可以执行导入操作的脚本,欢迎指正和优化。边的导入比较慢(单条导入)。
有两种优化思路:
一、Cypher 语句:
UNWIND [{startId:‘11’, endId:‘21’, relProps:{ hphm: ‘33’, sj: ‘44’ }},
{startId:‘22’, endId:‘23’, relProps:{ hphm: ‘44’, sj: ‘20080102’ }},
{startId:‘33’, endId:‘24’, relProps:{ hphm: '55, sj: ‘20120110’ }}] AS relData
MATCH (a:Ren {zjhm: relData.startId}), (b:Che {rowkey: relData.endId})
MERGE (a)-[r:sycl]->(b)
SET r += relData.relProps
RETURN r;

二、
https://tugraph-db.readthedocs.io/zh-cn/latest/development_guide.html Tugraph 官网的批量操作

CALL db.upsertEdge(‘edge1’,{type:‘node1’,key:‘node1_id’}, {type:‘node2’,key:‘node2_id’}, [{node1_id:1,node2_id:2,score:10},{node1_id:3,node2_id:4,score:20}])

代码里面留了

但 我的版本好像都不支持!!!

后文

在这里插入图片描述

欢迎讨论

相关文章:

neo4j 图表数据导入到 TuGraph

neo4j 图表数据导入到 TuGraph 代码文件说明后文 前言:近期在引入阿里的 TuGraph 图数据库,需要将 原 neo4j 数据导入到新的 tugraph 数据库中。预期走csv文件导入导出,但因为格式和数据库设计问题,操作起来比较麻烦(可能是个人没…...

启动报错java.lang.NoClassDefFoundError: ch/qos/logback/core/status/WarnStatus

报错信息图片 日志: Exception in thread "Quartz Scheduler [scheduler]" java.lang.NoClassDefFoundError: ch/qos/logback/core/status/WarnStatus先说我自己遇到的问题,我们项目在web设置了自定义的log输出路径,多了一个 / 去…...

【ubuntu18.04】ubuntu18.04挂在硬盘出现 Wrong diagnostic page; asked for 1 got 8解决方案

错误日志 [ 8754.700227] usb 2-3: new full-speed USB device number 3 using xhci_hcd [ 8754.867389] usb 2-3: New USB device found, idVendor0e0f, idProduct0002, bcdDevice 1.00 [ 8754.867421] usb 2-3: New USB device strings: Mfr1, Product2, SerialNumber0 [ 87…...

kubeadm安装K8s高可用集群之集群初始化及master/node节点加入calico网络插件安装

系列文章目录 1.kubeadm安装K8s高可用集群之基础环境配置 2.kubeadm安装K8s集群之高可用组件keepalivednginx及kubeadm部署 3.kubeadm安装K8s高可用集群之集群初始化及master/node节点加入集群calico网络插件安装 kubeadm安装K8s高可用集群之集群初始化及master/node节点加入ca…...

游戏何如防抓包

游戏抓包是指在游戏中,通过抓包工具捕获和分析游戏客户端与服务器之间传输的封包数据的过程。抓包工具可实现拦截、篡改、重发、丢弃游戏的上下行数据包,市面上常见的抓包工具有WPE、Fiddler和Charles Proxy等。 抓包工具有两种实现方式,一类…...

【LeetCode】每日一题 2024_12_19 找到稳定山的下标(模拟)

前言 每天和你一起刷 LeetCode 每日一题~ 最近力扣的每日一题出的比较烂,难度过山车,导致近期的更新都三天打鱼,两天断更了 . . . LeetCode 启动! 题目:找到稳定山的下标 代码与解题思路 先读题:最重要…...

运维 mysql、redis 、RocketMQ性能排查

MySQL查看数据库连接数 1. SHOW STATUS命令-查询当前的连接数 MySQL 提供了一个 SHOW STATUS 命令,可以用来查看服务器的状态信息,包括当前的连接数。 SHOW STATUS LIKE Threads_connected;这个命令会返回当前连接到服务器的线程数,即当前…...

[SAP ABAP] 将内表数据转换为HTML格式

从sflight数据库表中检索航班信息,并将这些信息转换成HTML格式,然后下载或显示在前端 开发步骤 ① 自定义一个数据类型 ty_sflight 来存储航班信息 ② 声明内表和工作区变量,用于存储表头、字段、HTML内容和航班详细信息以及创建字段目录lt…...

LLM大语言模型私有化部署-使用Dify与Qwen2.5打造专属知识库

背景 Dify 是一款开源的大语言模型(LLM) 应用开发平台。其直观的界面结合了 AI 工作流、 RAG 管道、 Agent 、模型管理、可观测性功能等,让您可以快速从原型到生产。相比 LangChain 这类有着锤子、钉子的工具箱开发库, Dify 提供了更接近生产需要的完整…...

使用C语言连接MySQL

在C语言中连接MySQL数据库,通常需要使用MySQL提供的C API。以下是使用C语言连接MySQL数据库的基本步骤和示例代码: 步骤 1: 安装MySQL C API 首先,确保你的系统上安装了MySQL数据库,并且安装了MySQL C API库。在大多数Linux发行版…...

PyTorch 2.0 以下版本中设置默认使用 GPU 的方法

PyTorch 2.0 以下版本中设置默认使用 GPU 的方法 在 PyTorch 2.0以下版本中,默认情况下仍然是使用 CPU 进行计算,除非明确指定使用 GPU。在 PyTorch 2.0 以下版本中,虽然没有 torch.set_default_device 的便捷方法,但可以通过显式…...

信号槽【QT】

文章目录 对象树字符集信号槽QT坐标系信号与槽connect自定义槽自定义信号disconnect 对象树 #ifndef MYLABEL_H #define MYLABEL_H#include<QLabel> class MyLabel : public QLabel { public:// 构造函数使用带 QWidget* 版本的.// 确保对象能够加到对象树上MyLabel(QWi…...

【UE5 C++课程系列笔记】10——动态单播/多播的基本使用

目录 概念 申明动态委托 一、DECLARE_DYNAMIC_DELEGATE 二、DECLARE_DYNAMIC_MULTICAST_DELEGATE 绑定动态委托 一、BindDynamic 二、AddDynamic 三、RemoveDynamic 执行动态委托 ​一、Execute 二、ExecuteIfBound 三、IsBound 四、Broadcast 动态单播使用示…...

点击展示大图预览

原文链接在table表格里能够实现&#xff0c;点击里面的图片实现大图预览的效果&#xff1b; 一、先安装viewer — 使用npm安装 npm install v-viewer --save二、在main.js中引入 import Viewer from v-viewer //点击图片大图预览 import viewerjs/dist/viewer.css Vue.use(…...

【C++】分书问题:深入解析、回溯法高级应用与理论拓展

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目描述&#x1f4af;思路与算法回溯法理论基础 &#x1f4af;代码实现与解析完整代码代码关键步骤解析 &#x1f4af;时间复杂度与空间复杂度分析&#x1f4af;理论拓展&…...

java开发入门学习五-流程控制

流程控制语句 if&#xff0c; if...else&#xff0c; if..else if..else 与前端相同 略 switch case 与前端不同的是case不能使用表达式&#xff0c;使用表达式会报错 class TestSwitch {public static void main(String[] args) {// switch 表达式只能是特定的数据类型…...

【FFmpeg 教程 一】截图

本章使用 ffmpeg 实现观影中经常会用到的功能&#xff0c;截图。 以下给出两种方式。 课程需具备的基础能力&#xff1a;Python 1. 使用 subprocess 调用 FFmpeg 命令 import subprocess def extract_frame(video_path, output_image_path, timestamp"00:00:05")&qu…...

北邮,成电计算机考研怎么选?

#总结结论&#xff1a; 基于当前提供的24考研复录数据&#xff0c;从报考性价比角度&#xff0c;建议25考研的同学优先选择北邮计算机学硕。主要原因是:相比成电&#xff0c;北邮计算机学硕的目标分数更低&#xff0c;录取率更高&#xff0c;而且北邮的地理位置优势明显。对于…...

深入了解京东API接口:如何高效获取商品详情与SKU信息

在当今数字化时代&#xff0c;电商平台的数据接口成为了连接商家与消费者的桥梁。京东作为国内领先的电商平台&#xff0c;其API接口为开发者提供了丰富的商品信息获取途径。本文将深入探讨如何使用京东API接口高效获取商品详情与SKU信息&#xff0c;并附上简短而实用的代码示例…...

C++常见内存泄漏案例分析以及解决方案

C 常见内存泄漏案例分析以及解决方案 1. 分配与释放不匹配 在动态内存管理中&#xff0c;使用new操作符分配的内存必须通过delete操作符显式释放。若未遵循这一规则&#xff0c;将导致内存泄漏。例如&#xff1a; int *p new int; p new int; // 错误&#xff1a;未释放先…...

[LeetCode-Python版]206. 反转链表(迭代+递归两种解法)

题目 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1] 示例 3&#xff1…...

70 mysql 中事务的隔离级别

前言 mysql 隔离级别有四种 未提交读, 已提交读, 可重复度, 序列化执行 然后不同的隔离级别存在不同的问题 未提交读存在 脏读, 不可重复度, 幻觉读 等问题 已提交读存在 不可重复度, 幻觉读 等问题 可重复读存在 幻觉读 等问题 序列化执行 没有以上问题 然后 我们这里…...

C语言二叉树

1.思维导图 树 二叉树 2.将链式队列重新实现一遍 linkqueue.c #include"linkqueue.h" linkqueuePtr create() {linkqueuePtr L(linkqueuePtr)malloc(sizeof(linkqueue));if(NULLL){printf("队列创建失败\n");return NULL;}L->head(nodePtr)malloc(si…...

智能工厂的设计软件 三种处理单元(NPU/GPU/CPU)及其在深度学习框架中的作用 之1

本文要点 深度学习&#xff1a;认知系统架构的处理层 在认知系统架构的设计和代码实现上 需要考虑多个层次&#xff0c;包括感知层、处理层、决策层和执行层。其中 深度学习主要用来解决处理层上的认知问题。 感知层&#xff1a;负责收集外部环境的信息。 处理层&#xff1a;…...

iOS swift开发系列--如何给swiftui内容视图添加背景图片显示

我需要在swiftui项目中显示背景图&#xff0c;有两种方式&#xff0c;一种是把图片拖入asset资源中&#xff0c;另外一种是直接把图片放在源码目录下。采用第一种方式&#xff0c;直接把图片拖到资源目录&#xff0c;但是swiftui项目没有弹出&#xff0c; “Copy items if need…...

jmeter后端监视器

一、概述 JMeter 后端监听器(Backend Listener)是 JMeter 提供的一个功能强大的插件,用于将测试执行期间收集的性能数据发送到外部系统进行监控和分析。通过后端监听器,您可以实时地将 JMeter 测试执行期间收集的数据发送到外部系统,如图形化展示、数据库、数据分析工具等…...

服务器数据恢复—RAIDZ离线硬盘数超过热备盘数导致阵列崩溃的数据恢复案例

服务器存储数据恢复环境&#xff1a; ZFS Storage 7320存储阵列中有32块硬盘。32块硬盘分为4组&#xff0c;每组8块硬盘&#xff0c;共组建了3组RAIDZ&#xff0c;每组raid都配置了热备盘。 服务器存储故障&#xff1a; 服务器存储运行过程中突然崩溃&#xff0c;排除人为误操…...

面试题整理4----lvs,nginx,haproxy区别和使用场景

LVS、Nginx、HAProxy&#xff1a;区别与使用场景 1. LVS&#xff08;Linux Virtual Server&#xff09;1.1 介绍1.2 特点1.3 使用场景 2. Nginx2.1 介绍2.2 特点2.3 使用场景 3. HAProxy3.1 介绍3.2 特点3.3 使用场景 4. 总结对比 在构建高可用、高性能的网络服务时&#xff0c…...

iOS - 超好用的隐私清单修复脚本(持续更新)

文章目录 前言开发环境项目地址下载安装隐私访问报告隐私清单模板最后 前言 在早些时候&#xff0c;提交应用到App Store审核&#xff0c;大家应该都收到过类似这样的邮件&#xff1a; Although submission for App Store review was successful, you may want to correct th…...

html <a>设置发送邮件链接、打电话链接 <a href=“mailto:></a> <a href=“tel:></a>

1.代码 <ul><li>电话&#xff1a;<a href"tel:18888888888">188-8888-8888</a></li><li>邮箱&#xff1a;<a href"mailto:10000qq.com">10000qq.com</a></li><li>邮箱&#xff1a;<a hre…...