如何在Neo4j Cypher查询中的索引属性上找到MAX

时间:2018-09-27 18:13:16

标签: neo4j cypher

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

节点有一个索引:

  • 创建约束(n:事务)ASSERT n.id是唯一的

我尝试查询:

  • 匹配(n:Transaction)返回n.id,按n.id DESC LIMIT 1排序
  • MATCH(n:Transaction)返回最大(n.id)

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

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

2 个答案:

答案 0 :(得分:0)

使用索引来优化ORDER BY查询的功能是现有的issue,并且计划在 neo4j 3.5 中实现-应该在最后淘汰今年(2018年)。

[编辑]

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

id

以上查询将使用索引快速找到{= {1}}值,该值> =最小值。

答案 1 :(得分:0)

由于@cybersam提到的Neo4j已知问题,我已经在客户端(java)端实施了临时变通方法以执行二进制搜索。它可以通过最多32个单节点查询来找到最大值,从而将运行时间减少到亚秒级,而原始单次调用的数据大小超过1亿个节点则只需一分钟以上。

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;
}