我正在努力改进商业网站的欺诈检测系统。我们处理直接银行交易,因此欺诈是我们需要管理的风险。我最近了解了图形数据库,并可以看到它如何应用于这些问题。所以,在过去的几天里,我设置了neo4j并将数据解析为:example
我的直觉是为每个订单创建一个节点,为每个订单创建一个节点,然后将它们连接在一起。像这样:
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数据库的期望。目前我们有大约17,000个节点。
答案 0 :(得分:0)
完全阅读developers manual总是一个好主意。
为了加快属性对节点的查找速度,您肯定需要创建indexes or unique constraints(取决于属性是否应对标签/值唯一)。
一旦您创建了所需的索引和约束,它们就会被您的查询所使用,以加快您的匹配。
START仅用于旧版索引,对于最新的Neo4j版本,您应该使用MATCH。如果您根据内部ID进行匹配,则可以使用MATCH (n) WHERE id(n) = xxx
。
请记住,您不应该在Neo4j之外保留节点ID以便在将来的查询中进行查找,因为内部节点ID可以在删除和创建节点时重复使用,因此曾经引用已被删除的节点的ID可能稍后最终指向一个完全不同的节点。
在查询中使用标签可以帮助您提高性能。在您查找订单的查询中,Neo4j必须检查路径中的每个终端节点以查看该属性是否存在。财产访问往往很昂贵,尤其是当您使用可变长度匹配时,因此最好通过标签限制所需的节点。
MATCH (a)-[:USED*]-(d:Order)
WHERE id(a) = 179
RETURN distinct d
在较大的图表上,可变长度匹配可能会开始减慢,因此您可以通过安装APOC Procedures并使用Path Expander过程收集所有子图节点并过滤到只是订单来获得更高的性能节点
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