Why are apoc.coll.max() and apoc.coll.min() deprecated in Cypher 25?

Why are apoc.coll.max() and apoc.coll.min() deprecated in Cypher 25? In the documentation, it is mentioned “This function is deprecated. Use Cypher’s max()or min() function instead.” Sounds easy, but using these leads to a completely different result unless applying an unwind before, but doing this might be very complex in difficult scenarios with large datasets.

max() and min() works with resulting rows while apoc.coll.max() and apoc.coll.min() just works with values of a collection from a single property. That collection values doesn’t need to come from a collect statement, they could be from any other source and might not be related to any nodes in the database. In a complex cypher with a big resultset it isn’t a good idea to unwind a big collection which will multiply the items in each collects with the results rows. Wouldn’t this be a totally unneccessary heavy load, except from beeing a quite ugly approach for retrieving a single collections max value.

Another option is to use REDUCE, but this is rather ugly in terms of readability and ease of maintenance.

Look, today we use:

apoc.coll.max([x in messages WHERE x.type = $commentType | datetime(x.created_at)]) as dateLastComment

In future we have to replace this with:

REDUCE(maxVal = null, date IN [x in messages WHERE x.type = $commentType | datetime(x.created_at)] | CASE WHEN date IS NOT NULL AND (maxVal IS NULL OR date > maxVal) THEN date ELSE maxVal END) as dateLastComment

This is nothing that easily comes to your mind when looking for a way to find the min or max value of a collection. And while doing a review, I just had big problems to read, understand and to approve this (which indeed was the trigger for this post).

So from my point of view, there is no valid replacement for apoc.coll.max() and apoc.coll.min() in the future.

Best,
Reiner

2 Likes

Personally, I agree, and similar goes for other apoc.coll functions that are currently deprecated in 2025.x.

We’ll raise some internal discussion on this. I believe there is value in concision, and in having the implementation wrapped up in a simple function, less chance to make a mistake in the more-complex native cypher version.

That said, if you use the suggested UNWIND and max(), it should probably be wrapped in a subquery CALL{}, that will help you scope to per-row execution (which you would get for free when using a function, since functions naturally execute per row).

1 Like

As a followup…

The deprecations here were jumping the gun. There was intention to implement these as native Cypher functions, but apparently that implementation was delayed.

Once we get those native Cypher functions as replacements, then the deprecation warnings will make much more sense, and it should be fairly easy to move away from the APOC versions.

In the meantime, until those replacements become available, you can ignore the deprecation warnings.

1 Like