用于欺诈检测的neo4j-高效的数据结构



我正在努力改进一个商业网站的欺诈检测系统。我们处理的是直接的银行交易,因此欺诈是我们需要管理的风险。我最近学会了绘制数据库图形,并可以看到它是如何应用于这些问题的。因此,在过去的几天里,我设置了neo4j,并将我们的数据解析到其中:示例

我的直觉是为每个订单创建一个节点,为与之相关的每一条数据创建一个结点,然后将它们连接在一起。像这样:

MATCH (w:Wallet),(i:Ip),(e:Email),(o:Order) 
WHERE w.wallet="ex" AND i.ip="ex" AND e.email="ex" AND o.refcode="ex" 
CREATE (w)-[:USED]->(o),(i)-[:USED]->(o),(e)-[:USED]->(o)

但是,随着数据库大小的增加,这个查询运行得非常慢(我认为是因为它需要在整个数据集中搜索我想要的节点)。运行这样的查询也需要很长时间:

START a=node(179) 
MATCH (a)-[:USED*]-(d) 
WHERE EXISTS(d.refcode) 
RETURN distinct d

这是为了提取连接到起点的所有订单。我是Cypher的新手(<24小时),我发现搜索解决方案特别困难。

我可以解决数据结构或查询方面的任何特定问题以提高性能吗?理想情况下,它需要在几秒钟内完成这类工作,正如我对SQL数据库所期望的那样。目前,我们有大约17000个节点。

完全阅读开发人员手册总是一个好主意。

为了加快属性对节点的查找,您肯定需要创建索引或唯一约束(取决于属性是否对标签/值是唯一的)。

一旦创建了所需的索引和约束,查询就会在后台使用它们来加快匹配速度。

START仅用于遗留索引,对于最新的Neo4j版本,您应该使用MATCH。如果您是基于内部id进行匹配的,则可以使用MATCH (n) WHERE id(n) = xxx

请记住,在未来的查询中,您不应该将节点id保留在Neo4j之外以供查找,因为在删除和创建节点时,内部节点id可以重复使用,因此曾经引用已删除节点的id后来可能会指向完全不同的节点。

在查询中使用标签应该有助于提高性能。在您为查找订单而进行的查询中,Neo4j必须检查路径中的每个端节点,以查看该属性是否存在。属性访问往往很昂贵,尤其是在使用可变长度匹配时,因此最好通过标签限制所需的节点。

MATCH (a)-[:USED*]-(d:Order)
WHERE id(a) = 179 
RETURN distinct d

在较大的图上,可变长度匹配可能会开始减慢,因此您可以通过安装APOC过程并使用路径扩展器过程来收集所有子图节点并过滤到仅Order节点来获得更高的性能。

MATCH (a)
WHERE id(a) = 179
CALL apoc.path.expandConfig(a, {bfs:true, uniqueness:"NODE_GLOBAL"}) YIELD path
RETURN LAST(NODES(path)) as d
WHERE d:Order

最新更新