简体   繁体   中英

How to find MAX on indexed property in Neo4j Cypher query

I need to find maximum on indexed unique property integer value.

Node has an index:

  • CREATE CONSTRAINT ON (n:Transaction) ASSERT n.id IS UNIQUE

I tried queries:

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

Both queries going through whole scan rather that use index.

How to optimize the query to quickly find maximum value?

The ability to use indexes for optimizing ORDER BY queries is an existing issue , and is scheduled to be implemented in neo4j 3.5 -- which should be out by the end of this year (2018).

[EDIT]

In the meantime, to avoid scanning all Transaction nodes, you can try performing a range query if you know a good min value for the max id . For example, if the last known max "id" was 10000:

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

The above query will use the index to quickly locate id values >= the minimum.

Due to known Neo4j's issue mentioned by @cybersam I've implemented temporary workaround on client (java) end to perform binary search. It finds max value with up to 32 single node queries that reduced runtime to subsecond compared to over a minute for original single call on data size over a hundred of millions nodes.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM