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);
4.5 知识体系:关联交易网络构建全景
下面这张图,是我自己总结的关联交易网络构建的核心逻辑。你可以把它当作一个检查清单:
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;
4.7 本章小结
这一章我们重点讲了:
- 为什么关联交易分析必须用图数据库——因为关系本身就是数据
- 三种核心关系:股权、任职、业务往来,缺一不可
- Neo4j的基本操作:建节点、建关系、批量导入
- 一个实战查询案例:隐性控制路径挖掘
说实话,图数据库的学习曲线并不陡。你只要理解了节点和关系这两个概念,剩下的就是多写Cypher语句。我个人建议你拿自己手头的数据试试,哪怕只有几十条记录,跑通一个路径查询,那种“原来如此”的感觉会让你彻底爱上图分析。
好,这一讲就到这里。下一讲我们会深入图算法,聊聊怎么用社区发现算法自动识别关联交易团伙——那才是真正的大杀器。
公众号:蓝海资料掘金营,微信deep3321