【问题标题】:How to find MAX on indexed property in Neo4j Cypher query如何在 Neo4j Cypher 查询中找到索引属性的 MAX
【发布时间】:2018-09-27 18:13:16
【问题描述】:

我需要找到索引唯一属性整数值的最大值。

节点有索引:

  • 在 (n:Transaction) 上创建约束断言 n.id 是唯一的

我试过查询:

  • MATCH (n:Transaction) 返回 n.id ORDER BY n.id DESC LIMIT 1
  • MATCH (n:Transaction) RETURN max(n.id)

两个查询都经过整个扫描而不是使用索引。

如何优化查询以快速找到最大值?

【问题讨论】:

    标签: neo4j cypher


    【解决方案1】:

    使用索引来优化ORDER BY 查询的能力是现有的issue,并计划在 neo4j 3.5 中实现——这应该会在今年年底推出( 2018)。

    [编辑]

    同时,为避免扫描所有 Transaction 节点,如果您知道最大id 的良好min 值,则可以尝试执行范围查询。例如,如果最后一个已知的最大“id”是 10000:

    MATCH (t:Transaction)
    WHERE t.id >= 10000
    RETURN node.id AS id
    ORDER BY id DESC
    LIMIT 1
    

    以上查询将使用索引快速定位id值>=最小值。

    【讨论】:

    • 感谢@cybersam 的快速回复。我现在可以使用解决方法吗?像存储过程或对max进行二进制搜索的东西?如果没有,我将在客户端手动编写一个。
    【解决方案2】:

    由于@cybersam 提到的已知 Neo4j 的问题,我在客户端 (java) 端实施了临时解决方法来执行二进制搜索。它通过多达 32 个单节点查询找到最大值,与原始单次调用超过一亿个节点的数据大小相比,运行时间减少到亚秒级。

    public int getLastTransactionId() {
        //return getInteger("MATCH (n:Transaction) RETURN n.id ORDER BY n.id DESC LIMIT 1").orElse(0);
    
        //Neo4j currently having issues with using inexes for ORDER or MAX
        //do binary search as a workaround
        return findMax("MATCH (n:Transaction {id:{id}}) RETURN n.id");
    }
    
    public int findMax(String query) {
        int minVal = 0;
        int maxVal = Integer.MAX_VALUE;
        while (minVal < maxVal) {
            int middle = (int) ((1L + minVal + maxVal) / 2);
            OptionalInt o = getInteger(query, Values.parameters("id", middle));
            log.debug("min:{}, max:{}, middle:{}, o:{}", minVal, maxVal, middle, o);
            if (o.isPresent()) {
                minVal = middle;
            } else {
                maxVal = middle - 1;
            }
        }
        return maxVal;
    }
    

    【讨论】:

      猜你喜欢
      • 2013-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多