交易欺诈圈 - 关系版本

1. 建模

本节将展示示例图上的 Cypher 查询示例。目的是说明查询的外观,并提供在实际设置中如何构造数据的指南。我们将在一个小型交易网络图上进行此操作,该图包含以环形结构连接的多个节点。

示例图将基于以下数据模型

1.1. 数据模型

fs transaction ring data relationship version model

1.1.1 必填字段

以下是入门所需的字段

Account 节点

  • accountNumber:包含账户的账户名。这可以更改为您用于 Account 的任何其他标识符。

TRANSACTION 关系

  • amount:包含账户之间转移的金额。

  • currency:包含交易的货币。

  • date:包含交易发生的日期。

1.2. 演示数据

以下 Cypher 语句将在 Neo4j 数据库中创建示例图

// Create all accounts
CREATE (a1:Account {accountNumber: 1})
CREATE (a2:Account {accountNumber: 2})
CREATE (a3:Account {accountNumber: 3})
CREATE (a4:Account {accountNumber: 4})


// Create relationships between accounts
CREATE (a1)-[:TRANSACTION {amount: 1000, currency: "gbp", date: datetime()-duration({days: 3})}]->(a2)
CREATE (a2)-[:TRANSACTION {amount: 900, currency: "gbp", date: datetime()-duration({days: 2})}]->(a3)
CREATE (a3)-[:TRANSACTION {amount: 810, currency: "gbp", date: datetime()-duration({days: 1})}]->(a4)
CREATE (a4)-[:TRANSACTION {amount: 729, currency: "gbp", date: datetime()}]->(a1)

1.3. Neo4j 模式

// Show neo4j scheme
CALL db.schema.visualization()

它将提供以下响应

fs transaction ring relationship version schema

摄取数据后,Neo4j 会解释图模式。在该模式中,我们可以观察到通过 TRANSACTION 关系连接到另一个 Account 节点的 Account 节点。尽管具有相同的标签,但 Account 节点拥有不同的属性,例如 accountNumber。然而,模式只考虑节点和关系上的标签。

2. Cypher 查询

2.1. 简单交易环

在此查询中,我们将识别一个符合以下要求的环

  • Account 节点应通过 TRANSACTION 关系连接。

  • 确保遵循交易方向(不是双向查询)。

  • 查找交易长度大于 3 且小于 7 的环。

// Identify simple transaction ring
MATCH path=(a:Account)-[:TRANSACTION*3..6]->(a)
RETURN path

2.2. 不含重复账户的交易环

在此查询中,我们将识别一个符合以下要求的环

  • Account 节点应通过 TRANSACTION 关系连接。

  • 确保遵循交易方向(不是双向查询)。

  • 查找交易长度大于 3 且小于 7 的环。

  • 确保环由唯一账户组成。

// Identify transaction ring with no duplicate accounts
MATCH path=(a:Account)-[:TRANSACTION*3..6]->(a)
// Here we ensure that one path has unique people involved in the chain
WHERE size(apoc.coll.toSet(nodes(path))) = size(nodes(path)) - 1
// Return all paths
RETURN path

2.3. 按时间顺序排列交易的交易环

在此查询中,我们将识别一个符合以下要求的环

  • Account 节点应通过 TRANSACTION 关系连接。

  • 确保遵循交易方向(不是双向查询)。

  • 查找交易长度大于 3 且小于 7 的环。

  • 确保环由唯一账户组成

  • 确保 TRANSACTION 关系按时间顺序排列

// Identify transaction ring where dates are in chronological order
MATCH path=(a:Account)-[rel:TRANSACTION*3..6]->(a)
// Here we ensure that one path has unique people involved in the chain
WHERE size(apoc.coll.toSet(nodes(path))) = size(nodes(path)) - 1
// Relationship validation
AND ALL(idx in range(0, size(rel)-2)
       // Ensures the dates are in chronological order
       WHERE (rel[idx]).date < (rel[idx+1]).date
   )
// Return all paths
RETURN path

2.4. 扣除 20% 金额的交易环

当资金通过欺诈圈时,账户之间转移的金额通常会因高达 20% 的手续费而减少。考虑到这一点,我们的查询将允许每次交易减少高达 20%。

在此查询中,我们将识别一个符合以下要求的环

  • Account 节点应通过 TRANSACTION 关系连接。

  • 确保遵循交易方向(不是双向查询)。

  • 查找交易长度大于 3 且小于 7 的环。

  • 确保环由唯一账户组成

  • 确保 TRANSACTION 关系按时间顺序排列

  • 检查 TRANSACTION 金额是否在前一笔交易的 20% 范围内。

// Identify transaction ring where amounts are within 20% of each other
MATCH path=(a:Account)-[rel:TRANSACTION*3..6]->(a)
// Here we ensure that one path has unique people involved in the chain
WHERE size(apoc.coll.toSet(nodes(path))) = size(nodes(path)) - 1
// Relationship validation
AND ALL(idx in range(0, size(rel)-2)
       // Ensures the dates are in chronological order
       WHERE (rel[idx]).date < (rel[idx+1]).date
       // Checks that there is less than a 20% difference from the last `TRANSACTION` amount to the next
       AND (rel[idx+1].amount / rel[idx].amount) * 100 <= 20
   )
// Return all paths
RETURN path

2.4.1. 此查询的作用是什么?

给定的 Cypher 查询旨在识别图数据库中账户通过交易连接的可疑交易环。该查询查找符合特定条件的交易循环,然后返回这些循环。让我们逐步分解查询。

1 - 查找循环路径

MATCH path=(a:Account)-[rel:TRANSACTION*3..6]→(a)

此行启动 MATCH 子句,查找账户 (a:Account) 通过 3 到 6 个 TRANSACTION 关系 (rel:TRANSACTION*3..6) 连接到自身的路径。这些路径形成循环,代表一个交易“环”。

2 - 确保账户唯一

WHERE size(apoc.coll.toSet(nodes(path))) = size(nodes(path)) - 1

此函数将路径中的节点列表转换为集合,从而有效地删除任何重复项。

size(nodes(path)) - 1

这计算了路径中节点列表的大小,减去 1 以考虑循环中起始节点和结束节点相同的情况。

WHERE 子句确保循环中的所有账户都是唯一的。

3 - 关系验证

AND ALL(idx in range(0, size(rel)-2) WHERE (rel[idx]).date < (rel[idx+1]).date AND (rel[idx+1].amount / rel[idx].amount) * 100 ⇐ 20 )

ALL(idx in range(0, size(rel)-2))

这使用从 0 到 size(rel) - 2 的索引迭代路径中的每个关系。

(rel[idx]).date < (rel[idx+1]).date

检查交易日期是否按时间顺序排列。

(rel[idx+1].amount / rel[idx].amount) * 100 ⇐ 20

检查每笔后续交易的金额是否在前一笔交易金额的 20% 范围内。

4 - 返回路径

RETURN path

此行返回满足上述所有条件的路径。

摘要:该查询识别由 3 到 6 笔唯一账户间交易组成的交易环。它通过确保交易金额变化不超过 20% 且交易按时间顺序排列来进一步验证这些环。

© . All rights reserved.