【问题标题】:Neo4j: Maintaining node countsNeo4j:维护节点数
【发布时间】:2016-12-02 14:48:50
【问题描述】:

我正在研究使用 Neo4j 近乎实时地检测潜在的欺诈性卡交易。我从我们的在线系统收到客户的详细信息和他们刚刚使用的卡。我在这里尝试做的是为客户和卡创建新节点(如果它们不存在),然后建立它们之间的关系。

每当客户使用卡时我想设置卡的最后使用时间,另外,如果这是第一次看到这个客户-->卡关系已经看到,更新客户卡的总数与卡相关联以及与卡相关联的客户数量。

下面的 Cypher 似乎有效,但我认为它会在每次看到关系时重新评估计数,而不仅仅是在创建时。是否可以在此语句中使用 ON MATCH 和 ON CREATE 来限制不必要的处理?

MERGE (c:customers {customer_id:"12345678"})
MERGE (a:cards {card_hash:"45uIic..."})
MERGE (c)-[r:has_card]->(a)
set r.last_transaction = "30-NOV-2016 07:58:42"
set a.card_ct = size(()-[:has_card]->(a))
set c.card_count = size((c)-[:has_card]->())

我正在从 Python 运行它(使用 py2neo),我还想返回一些东西,这将允许我开始定制的基于 dijkstra 的邻域搜索。有什么想法可以根据这是新关系还是现有关系返回一些变量?

【问题讨论】:

    标签: neo4j cypher


    【解决方案1】:

    您甚至不需要拥有card_ctcard_count 属性。

    从 neo4j 2.1 开始,从节点获取特定类型的关系数量非常有效。因此,每次需要计数时,只需使用 SIZE(()-[:has_card]->(node))SIZE((node)-[:has_card]->())

    【讨论】:

    • 我在节点上保存了关系属性的数量,以便它在 Neo4j 浏览器中可见,我发现查看与卡(或银行或电话)关联的客户数量更有用number...) 而不是诸如卡号哈希之类的详细信息。对于客户来说,在尝试扩展节点之前,计算与他们关联的卡的数量等很有用。
    • 您不应该根据在浏览器中易于可视化的内容来设计数据模型。您应该设计它以使您的实际用例高效。您始终可以按照我建议的方式在浏览器中执行查询,按计数对结果进行排序,然后以表格或文本形式在浏览器中查看结果。
    【解决方案2】:

    这样的事情怎么样。在 MATCH 上创建一个计数器,如果计数器大于零,则它是一个现有关系。否则就是新的关系。

    MERGE (c:customers {customer_id:"12345678"})
    MERGE (a:cards {card_hash:"45uIic..."})
    MERGE (c)-[r:has_card]->(a)
    ON MATCH SET r.num = coalesce(r.num, 0) + 1
    set r.last_transaction = "30-NOV-2016 07:58:42"
    set a.card_ct = size(()-[:has_card]->(a))
    set c.card_count = size((c)-[:has_card]->())
    RETURN 
    CASE 
      WHEN r.num > 0 THEN false
      ELSE true
    END as new_relationship 
    

    【讨论】:

    • 谢谢,这正是我所需要的。还意识到我不应该在每一行上使用新的 SET,只需使用逗号分隔 ON MATCH 后面的语句就可以了。
    【解决方案3】:

    这是我最终得到的 Cypher,感谢 Dave Bennett 的建议。我还意识到,如果只有 1 个客户与 1 张卡相关联,我不需要启动任何进一步的分析,因此我也将其排除在外。

    MERGE (c:customers {customer_id:"12345678"})
    MERGE (a:cards {card_hash:"BFgn..."})
    MERGE (c)-[r:has_card]->(a)
    ON CREATE SET a.card_scheme = "VISA DEBIT"
                , a.card_ct = size(()-[:has_card]->(a))
                , c.card_count = size((c)-[:has_card]->())
    ON MATCH SET r.ind = 1
    SET r.last_transaction = "06-Dec-2016 11:19:13"
    RETURN CASE WHEN exists(r.ind) 
                     AND a.card_ct + c.card_count > 2 
                     THEN false 
                     ELSE true END as new_relationship
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-11
      • 2018-03-02
      • 2014-06-15
      相关资源
      最近更新 更多