4. Cypher入门
Cypher是Neo4j的声明式图查询语言,它的设计目标不是告诉数据库“怎么一步步做”,而是描述“我想要什么样的图模式”。在反欺诈场景中,我们关心的往往不是单条记录,而是“谁通过什么设备、在什么时间、与谁发生了资金往来”。Cypher正是用接近ASCII图形的语法,把这种关系模式直接表达出来。掌握本章的基础子句,是后续构建欺诈团伙识别、资金环路检测、异常设备聚集等模型的前提。
核心原理:Cypher的声明式与模式匹配
Cypher的核心思想是模式匹配。节点用圆括号表示,关系用方括号加箭头表示,例如 (a:Account)-[:TRANSFER]->(b:Account) 描述了一个账户向另一个账户转账的模式。查询时,数据库引擎负责决定从哪个节点开始、走哪条索引、以什么顺序展开,而用户只需声明目标模式。
Cypher的执行流程可以概括为“解析—规划—执行—返回”四个阶段。解析阶段检查语法与语义;规划阶段生成执行计划,决定使用节点标签索引、关系类型索引还是全表扫描;执行阶段按计划逐行产生结果;返回阶段由RETURN决定输出哪些列。理解这一点很重要:WHERE写在MATCH之后并不代表它最后执行,优化器会尽量把过滤条件下推,减少中间结果规模。
关键认知:Cypher是声明式的,但性能仍然取决于你是否为标签和属性建立了索引,以及模式是否能让规划器选择高选择性的起点。
方法流程:从读取到写入的八个基础子句
下面按“读—过滤—写—改—删”的顺序梳理最常用的八个子句。
MATCH:声明要匹配的图模式,是读取数据的入口。RETURN:指定查询结果中返回的列、别名、聚合或排序。WHERE:对MATCH或WITH产生的行进行过滤,支持布尔运算、字符串、数值、存在性判断。CREATE:无条件创建节点、关系或路径,重复执行会产生重复数据。MERGE:先匹配,匹配不到再创建,常用于幂等写入和去重。SET:修改节点或关系的属性,也可添加标签。REMOVE:移除属性或标签,不删除节点本身。DELETE:删除节点或关系;删除有关系的节点需先删关系或使用DETACH DELETE。
一个典型的反欺诈查询流程是:先用MATCH定位可疑账户,用WHERE过滤时间窗口和金额阈值,用RETURN输出路径与统计值;若需要落库标记,再用SET写入风险标签。写入时优先考虑MERGE,避免重复导入造成图谱膨胀。
// 查询近7天内同一设备登录过的多个账户
MATCH (d:Device)<-[:USED_BY]-(a:Account)
WHERE d.lastSeen >= datetime() - duration('P7D')
WITH d, collect(DISTINCT a) AS accounts
WHERE size(accounts) >= 3
RETURN d.deviceId AS deviceId,
[x IN accounts | x.accountNo] AS accountNos,
size(accounts) AS accountCount
ORDER BY accountCount DESC
LIMIT 20;
这段查询先匹配设备与账户的使用关系,过滤最近七天活跃的设备,再按设备聚合账户,最后筛选出关联账户数不少于3个的设备。它体现了MATCH、WHERE、WITH、RETURN的协作方式,也是反欺诈中“设备聚集”特征的常见写法。
案例场景:用MERGE与SET维护风险名单
假设我们已有一批高风险账户,需要将其标记为RiskAccount标签,并记录风险等级和更新时间。若直接使用CREATE,每次执行都会新增节点,导致同一账户重复。正确做法是先用MERGE按唯一业务键匹配,再SET属性。
UNWIND $accounts AS row
MERGE (a:Account {accountNo: row.accountNo})
ON CREATE SET a.createdAt = datetime()
SET a:RiskAccount,
a.riskLevel = row.riskLevel,
a.riskUpdatedAt = datetime()
RETURN a.accountNo, a.riskLevel;
这里MERGE保证了账户节点的唯一性,ON CREATE只在新建时设置创建时间,SET则无论新建还是匹配都会更新风险等级。若某账户不再属于风险名单,可用REMOVE移除标签,而不是删除节点:
MATCH (a:Account {accountNo: $accountNo})
REMOVE a:RiskAccount
SET a.riskUpdatedAt = datetime()
RETURN a;
当确实需要清理测试数据时,删除节点前必须处理关系。若节点存在关系,直接DELETE会报错,此时可使用DETACH DELETE先断开所有关系再删除节点。
MATCH (a:Account {accountNo: 'TEST001'})
DETACH DELETE a;
注意:DETACH DELETE会删除节点及其所有关系,生产环境务必先用MATCH加RETURN count(*)确认影响范围,避免误删核心图谱数据。
误区复盘:常见错误与执行顺序
初学者最容易犯的错误有三类。第一,把WHERE写在MATCH之前,语法不允许;第二,用CREATE代替MERGE做幂等写入,导致重复节点;第三,忽略WITH的作用域,在聚合后直接引用未聚合字段。下表汇总了常见误区与修正方式。
| 误区 | 典型表现 | 修正方式 |
|---|---|---|
| 过滤位置错误 | 在MATCH前写WHERE | 将WHERE紧跟MATCH或WITH |
| 重复写入 | 反复执行CREATE产生重复账户 | 改用MERGE按业务唯一键匹配 |
| 聚合后引用错误 | RETURN d, collect(a), a.name | 用WITH先聚合,再引用聚合结果 |
| 删除有关系的节点 | DELETE报错“still has relationships” | 先删关系或使用DETACH DELETE |
| 忽略索引 | 按属性匹配全表扫描 | 为高频过滤属性建立索引或唯一约束 |
关于执行顺序,可以记住一个简化模型:MATCH产生行,WHERE过滤行,WITH传递并重塑行,RETURN输出行。写操作子句CREATE、MERGE、SET、REMOVE、DELETE则在读取结果的基础上逐行执行。理解这个流水线,能帮助你在反欺诈建模中写出既正确又高效的Cypher。
实践建议:在反欺诈图谱中,账户号、设备号、手机号、IP等业务唯一键应建立唯一约束,配合MERGE使用,既能保证幂等导入,又能让规划器利用索引快速定位起点。