我正在学习neo4j的基础知识,我正在查看以下带有信用卡欺诈的示例https://linkurio.us/stolen-credit-cards-and-fraud-detection-with-neo4j。 Cypher查询找到所有被盗用户购物的商店
MATCH (victim:person)-[r:HAS_BOUGHT_AT]->(merchant)
WHERE r.status = “Disputed”
MATCH victim-[t:HAS_BOUGHT_AT]->(othermerchants)
WHERE t.status = “Undisputed” AND t.time < r.time
WITH victim, othermerchants, t ORDER BY t.time DESC
RETURN DISTINCT othermerchants.name as suspicious_store, count(DISTINCT t) as count, collect(DISTINCT victim.name) as victims
ORDER BY count DESC
但是,当用户数量增加时(比如数百万用户),此查询可能会变慢,因为初始查询必须遍历标记为person的所有节点。是否可以通过将属性设置为节点而不是事务来加速查询?我试图从关系中删除“status”属性并将其添加到节点(用户,而不是商家)。但是,当我使用约束WHERE victim.status="Disputed"
运行查询时,查询不会返回任何内容。所以,在我的情况下,人有一个额外的财产'状态'。我认为我做了很多错事,但会很感激评论。例如
MATCH (victim:person)-[r:HAS_BOUGHT_AT]->(merchant)
WHERE victim.status = “Disputed”
返回正确数量的争议交易。同样适用于单独查询无争议交易的数量。但是,合并后,它们会产生一个空集。
如果我在方法中犯了错误,我怎样才能加快对大量节点的查询速度(避免在第一步中遍历所有节点)。我将使用具有类似属性的数据集,但将拥有大约1亿用户,因此我想在其他属性上为用户编制索引。
答案 0 :(得分:1)
[被修改]
将status
属性从关系移动到person
节点似乎不是正确的方法,因为我认为同一个人可以是多个商家的客户。
相反,您可以将关系重新定义为节点(让它标记为purchase
),如:
(:person)-[:HAS_PURCHASE]->(:purchase)-[:BOUGHT_AT]->(merchant)
purchase
个节点可以具有status
属性。你只需要创建索引:
CREATE INDEX ON :purchase(status)
此外,您可以将time
属性放在新的purchase
节点中。
通过上述操作,您的查询将变为:
MATCH (victim:person)-[:HAS_PURCHASE]->(pd:purchase)-[:BOUGHT_AT]->(merchant)
WHERE pd.status = “Disputed”
MATCH victim-[:HAS_PURCHASE]->(pu:purchase)-[:BOUGHT_AT]->(othermerchants)
WHERE pu.status = “Undisputed” AND pu.time < pd.time
WITH victim, othermerchants, pu ORDER BY pu.time DESC
RETURN DISTINCT othermerchants.name as suspicious_store, count(DISTINCT pu) as count, collect(DISTINCT victim.name) as victims
ORDER BY count DES