---
title: Heavy Hitters And Collection Aggregates
url: https://nexyron.tech/docs/cypher/functions/aggregation/heavy-hitters-and-collection-aggregates
description: Use this family when you need to preserve or summarize the values themselves rather than only collapse everything to one scalar number. Documenting it separately matters because ag
---

# Heavy Hitters And Collection Aggregates

## Generic Description

Use this family when you need to preserve or summarize the values themselves rather than only collapse everything to one scalar number. Documenting it separately matters because aggregate placement changes row grain, grouping behavior, and whether state/merge forms are valid.

Simple example:

```cypher
MATCH (u:User)-[:HAS_APP_SESSION]->(s:AppSession)
RETURN top_k(s.mode, 3) AS hottest_modes,
       collect(DISTINCT s.mode) AS distinct_modes,
       group_concat(s.mode, '|') AS mode_path
```

## Consumer-Level Explanation

This family is about two related but different jobs:

-   heavy hitters: which values dominate a grouped population?
-   collection-preserving summaries: which values did I actually see, and in what retained order or concatenated form?

The current implemented surface includes:

-   `top_k`
-   `heavy_hitters`
-   `collect`
-   `group_concat`
-   `listagg`
-   `first`
-   `last`
-   `sample`

These are useful when plain scalar summaries are too lossy. In social, content, or operational data, you often care about the leading categories, an ordered sample, or a retained list of labels or modes.

## More Detailed Explanation

`top_k` and `heavy_hitters` are about exact frequency ranking on the current engine path. They are not just a convenience alias for sorting rows outside the query. They preserve the idea that “most common values” is part of the aggregate layer itself.

`collect`, `group_concat`, `first`, `last`, and `sample` matter for a different reason: they keep value identity around. That makes them useful in:

-   rollups that still need examples
-   ordered session-mode or state summaries
-   collection-oriented post-processing in later Cypher steps

The current implementation also pushes a large part of this family into:

-   aggregate state / merge forms
-   spill-backed grouped execution for the supported exact subset
-   exact incremental materialized-view maintenance on the safe subset

That is a meaningful architectural improvement because ordered and collection-oriented aggregates are usually where systems fall back to “refresh everything.”

## Advanced Example

```cypher
MATCH (u:User)-[:HAS_APP_SESSION]->(s:AppSession)
WITH u.profile.location.country AS country,
     s
RETURN country,
       top_k(s.mode, 2) AS hottest_modes,
       collect(DISTINCT s.entry_point) AS distinct_entry_points,
       group_concat(DISTINCT s.entry_point, '|') AS entry_points_joined,
       first(s.mode) AS first_mode,
       last(s.mode) AS last_mode,
       sample(s.mode) AS sample_mode
ORDER BY country
```

## Real Use Cases

-   social analytics where the top interaction types or session modes matter more than only raw counts
-   content analytics where category lists or joined labels are used for reporting and exports
-   operational timelines where an ordered first/last state is needed alongside scalar metrics

## Real Limitations And Tradeoffs

-   collection-preserving aggregates can grow result size quickly when groups are large
-   order-sensitive aggregates are inherently harder to maintain incrementally than pure scalar aggregates
-   heavy-hitter results are only as useful as the grouped slice; broad noisy groups produce broad noisy leaders
