4、关联交易网络构建:基于股权关系、人员任职、业务往来的网络建模,图数据库(Neo4j)基础

好,咱们进入第四讲。前面几章我们把关联交易的识别逻辑、数据清洗讲得差不多了。但说实话,光靠Excel或者关系型数据库,你很难看清那些错综复杂的利益链条。你想想看,A公司控股B,B的董事又是C的创始人,C又跟A有大量资金往来——这种网状结构,用传统表格去查,查到你怀疑人生。

所以这一章,我带你走进图的世界。咱们聊聊怎么用图数据库(Neo4j)来构建关联交易网络。我个人习惯把这一步叫做“把数据变成关系图谱”。

4.1 为什么非要用图?

先问个问题:你手头有1000家公司,每家公司有5个股东、3个高管,还有一堆上下游合同。你想查“张三通过哪些路径控制了李四的公司”?

用SQL写递归查询?能写,但性能会随着层级变深急剧下降。而且你很难直观地看到“路径”。

图数据库就不一样了。它把“公司”、“人”看作节点(Node),把“持股”、“任职”、“交易”看作关系(Relationship)。查询“张三到李四公司的路径”,就是一条简单的图遍历语句,毫秒级返回。

我在项目中遇到过一家集团企业,光子公司就200多家,交叉持股、循环持股特别多。用传统方式做关联方排查,审计团队花了三周。后来我用Neo4j重建了股权网络,半天就挖出了三条隐性控制链。嗯,这就是图的威力。

核心思想: 关联交易的本质是“关系”,而图数据库是存储和查询关系的最佳工具。

4.2 网络建模:三种核心关系

构建关联交易网络,我们主要关注三类关系。我把它们称为“铁三角”:

  • 股权关系: 谁控股谁?持股比例多少?这是最硬的关系。
  • 人员任职: 谁在谁那里当董事、监事、高管?这是“人”的纽带。
  • 业务往来: 谁跟谁有采购、销售、资金拆借?这是交易本身。

你想想看,这三类关系叠加在一起,才能完整刻画一个关联交易网络。光有股权,可能只是资本运作;光有业务,可能是正常交易;但一旦股权+任职+业务同时出现,那基本就是关联交易的高危信号了。

4.3 图数据模型设计

在Neo4j里,我们通常这样设计节点和关系:

节点类型 标签(Label) 主要属性
公司 Company name, credit_code, industry, registered_capital
自然人 Person name, id_card, phone
交易 Transaction amount, date, type, contract_no

关系类型设计:

关系类型 起点 终点 属性
HOLDS_SHARE Person / Company Company ratio, amount
IS_DIRECTOR Person Company position, start_date
HAS_TRANSACTION Company Company amount, direction, date

我个人习惯给每个节点加一个唯一ID(比如统一社会信用代码或身份证号),这样后续做去重和合并会方便很多。避坑指南:我曾经因为没做ID归一化,导致同一个公司在图里出现了两个节点,查路径时死活查不到——后来排查了整整一天才发现是数据源里公司名称写法不一致。

4.4 Neo4j 基础操作:建库、建点、建关系

好,咱们动手。假设你已经装好了Neo4j(社区版免费,够用)。打开浏览器,进入Neo4j Browser,咱们开始写Cypher语句。

4.4.1 创建节点

// 创建公司节点
CREATE (c:Company {name: '蓝海集团', credit_code: '91110000MA12345678', industry: '制造业'});

// 创建自然人节点
CREATE (p:Person {name: '张三', id_card: '110101199001011234'});

4.4.2 创建关系

// 张三持股蓝海集团60%
MATCH (p:Person {name: '张三'})
MATCH (c:Company {name: '蓝海集团'})
CREATE (p)-[:HOLDS_SHARE {ratio: 0.6, amount: 60000000}]->(c);

// 张三担任蓝海集团董事
MATCH (p:Person {name: '张三'})
MATCH (c:Company {name: '蓝海集团'})
CREATE (p)-[:IS_DIRECTOR {position: '董事', start_date: '2020-01-01'}]->(c);

4.4.3 批量导入(实战推荐)

实际项目中,数据量动辄几十万条,一条条CREATE不现实。我建议用LOAD CSV或者APOC插件批量导入。下面是一个典型的CSV导入示例:

// 导入公司节点
LOAD CSV WITH HEADERS FROM 'file:///companies.csv' AS row
CREATE (c:Company {
  name: row.name,
  credit_code: row.credit_code,
  industry: row.industry
});

// 导入持股关系
LOAD CSV WITH HEADERS FROM 'file:///shareholdings.csv' AS row
MATCH (holder:Person {id_card: row.holder_id})
MATCH (company:Company {credit_code: row.company_code})
CREATE (holder)-[:HOLDS_SHARE {ratio: toFloat(row.ratio)}]->(company);
小技巧: 导入前先用CREATE CONSTRAINT给关键字段建唯一索引,比如公司credit_code、人员id_card。这样能避免重复节点,导入速度也会快很多。

4.5 知识体系:关联交易网络构建全景

下面这张图,是我自己总结的关联交易网络构建的核心逻辑。你可以把它当作一个检查清单:

关联交易网络构建核心逻辑 数据源层 工商登记数据 人员任职数据 交易流水数据 建模层(三种核心关系) 股权关系 (HOLDS_SHARE) 人员任职 (IS_DIRECTOR) 业务往来 (HAS_TRANSACTION) 存储层:Neo4j 图数据库 节点(Company / Person / Transaction)+ 关系(持股/任职/交易) 应用层:风险识别与挖掘 路径查询 | 环路检测 | 社区发现 | 异常交易预警

4.6 实战案例:快速查询隐性关联

假设我们已经建好了图。现在想查“张三通过哪些公司间接控制了蓝海集团”?

// 查询张三到蓝海集团的所有控制路径(深度不超过5层)
MATCH path = (p:Person {name: '张三'})-[:HOLDS_SHARE*1..5]->(c:Company {name: '蓝海集团'})
RETURN path;

这条语句会返回所有从张三出发,经过1到5层持股关系,最终到达蓝海集团的路径。结果会以图形化方式展示,非常直观。

再比如,你想查“哪些公司与蓝海集团既有股权关系,又有业务往来”?

// 查询同时存在持股和交易关系的公司
MATCH (c1:Company {name: '蓝海集团'})<-[:HOLDS_SHARE]-(holder)
MATCH (c1)-[:HAS_TRANSACTION]->(c2:Company)
WHERE holder = c2 OR holder <> c2
RETURN c1, holder, c2;
注意: 图查询虽然快,但深度不宜过大。我一般限制在5层以内,超过5层的路径在实际业务中往往已经失去控制意义,而且查询性能会明显下降。曾经有个同事查10层路径,结果数据库直接卡死了——嗯,这是个教训。

4.7 本章小结

这一章我们重点讲了:

  • 为什么关联交易分析必须用图数据库——因为关系本身就是数据
  • 三种核心关系:股权、任职、业务往来,缺一不可
  • Neo4j的基本操作:建节点、建关系、批量导入
  • 一个实战查询案例:隐性控制路径挖掘

说实话,图数据库的学习曲线并不陡。你只要理解了节点和关系这两个概念,剩下的就是多写Cypher语句。我个人建议你拿自己手头的数据试试,哪怕只有几十条记录,跑通一个路径查询,那种“原来如此”的感觉会让你彻底爱上图分析。

好,这一讲就到这里。下一讲我们会深入图算法,聊聊怎么用社区发现算法自动识别关联交易团伙——那才是真正的大杀器。


公众号:蓝海资料掘金营,微信deep3321