尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Python 操作 Neo4j,别一上来就用 for 循环写节点

发布时间:2026/9/11 19:25:11

资讯中心
01
ARTICLE

Python 操作 Neo4j,别一上来就用 for 循环写节点

Python 操作 Neo4j,别一上来就用 for 循环写节点
将一批用户关系导入到Neo4j中, 脚本运行时没有出现报错情况, 日志所显示的内容也全都表明是成功的, 然而数据库里的节点数量却在运行过程中越来越多。像这种问题, 我通常情况下, 不会首先去怀疑Neo4j, 而是会先去查看写入代码。果真如此, 外层存在着一个for循环, 在其里面, 每一次执行的时候呢只是执行一条。脚本重新运行一次, 数据紧跟着就会被复制一遍。图数据库写起来的时候, 看着是比较直观的。然而, 真正容易出现问题的那些地方, 却是唯一约束, 还有批量写入, 以及事务边界。连接 Neo4j用官方驱动就够了pip install neo4j不能够让连接代码, 零碎地分布于业务函数之中, 而且, 绝对不可以每处理一条数据, 便去创建一次。import os from neo4j import GraphDatabase defbuild_driver: uri os.getenv(NEO4J_URI, neo4j://127.0.0.1:7687) user os.getenv(NEO4J_USER, neo4j) password os.environ[NEO4J_PASSWORD] driver GraphDatabase.driver(uri, auth(user, password)) driver.verify_connectivity return driverNeo4j官方驱动能够借助.来开展执行操作, 并且运用参数进行传值。密码切勿写死于代码当中, 此类事物早晚将会被提交至仓库。开始导数据前我会先把唯一约束建好。definit_schema(driver): driver.execute_query( CREATE CONSTRAINT user_uid_unique IF NOT EXISTS FOR (u:User) REQUIRE u.uid IS UNIQUE , database_neo4j, )要是没有这样的约束, 下面有着 MERGE 运用的这条语句, 一旦数据模型给写得杂乱无章, 后续去排列重复节点, 那依旧是会麻烦的。仅是唯一约束, 并非仅仅是对脏数据加以拦截, 其背后并且会构建起与之对应的索引, 当已然存在重复数据之际, 约束的创建极有可能会直接遭遇失败, 就在这个时段, 切莫反复去执行脚本, 先要把重复的节点查找出来并予以处理。真正写用户节点时别这么干for user in users: driver.execute_query( CREATE (:User {uid: $uid, name: $name}), uiduser[uid], nameuser[name], )问题有两个一条数据一次网络交互而且脚本不能安全重跑。我通常把数据切成小批次再用 展开。defimport_users(driver, users, chunk_size800): cypher UNWIND $rows AS row MERGE (u:User {uid: row.uid}) SET u.name row.name, u.department row.department, u.updated_at datetime for offset in range(0, len(users), chunk_size): rows users[offset: offset chunk_size] driver.execute_query( cypher, rowsrows, database_neo4j, )会将参数里的列表呈现为展开成为多行的形式, 后续的 MERGE 以及 SET 便能够依照行来进行处理, 相较于在外面逐个逐条地进行提交, 要干净许多得多。写入关系也还算可以, 然而这儿存在一处地方, 不少人我都见过在这个地方写错: 把能够发生变化的属性塞进到MERGE当中。defimport_follow_relations(driver, relations): driver.execute_query( UNWIND $links AS link MATCH (source:User {uid: link.source_uid}) MATCH (target:User {uid: link.target_uid}) MERGE (source)-[r:FOLLOWS]-(target) ON CREATE SET r.created_at datetime SET r.channel link.channel, r.updated_at datetime , linksrelations, database_neo4j, )这里, MERGE所承担的职责仅仅是判定关系有无存在的情况, 而这种说不定会出现改变的字段, 则是放置于SET当中句号。要是写成下面这样MERGE (source)-[:FOLLOWS {channel: link.channel}]-(target)用户更改一回关注途径或许就会多生出一条关系, 语法并无差错, 然而模型有误, 并且这类问题一般要等查询至结果循环之时才为人察见。查询图关系时也别一兴奋就写无限深度路径。deffind_following(driver, uid, max_rows50): records, _, _ driver.execute_query( MATCH path (:User {uid: $uid})-[:FOLLOWS*1..2]-(target:User) RETURN DISTINCT target.uid AS uid, target.name AS name, length(path) AS distance ORDER BY distance, uid LIMIT $limit , uiduid, limitmax_rows, database_neo4j, ) return [record.data() for record in records]1..2 这个范围, 是不可以随手就删除的。在关系密集的图当中, 当路径深度放开以后, 中间结果是有可能迅速膨胀起来的。倘若页面仅仅展现几十条数据, 那就不要让数据库先把整张关系网都翻上一遍。还有一种操作必须放在事务里先删除旧关系再重建新关系。defreplace_document_tags(driver, document_id, tags): defwrite_tags(tx): tx.run( MATCH (:Document {id: $document_id})-[r:HAS_TAG]- DELETE r , document_iddocument_id, ).consume tx.run( MATCH (doc:Document {id: $document_id}) UNWIND $tags AS tag_name MERGE (tag:Tag {name: tag_name}) MERGE (doc)-[:HAS_TAG]-(tag) , document_iddocument_id, tagstags, ).consume with driver.session(databaseneo4j) as session: session.execute_write(write_tags)成功删除了过后又出现重建失败的情况, 文档标签就变为空的状态了。将两个动作放入到同一个事务之中, 要么一起进行提交, 要么一起进行回滚。它本身会自动运用事务当涉及到多条查询以及中间处理的时候, 再去使用这种托管事务。最后别忘了关连接defrun_import(users, relations): driver build_driver try: init_schema(driver) import_users(driver, users) import_follow_relations(driver, relations) finally: driver.close操作 Neo4j 的代码不算多坑主要藏在 里。是否存在稳定业务主键于节点, MERGE所匹配的是哪些字段, 关系可不可以重复路径最大能查询到几层, 批量任务失败之后可不可以重新运行——在这些地方不预先考虑明白清晰清楚, 即便驱动连接再怎么美观漂亮好看也毫无作用用处价值。尤其是那个套着 的 for 循环看见了就尽早删。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。