LIMIT

The LIMIT clause restricts the number of rows returned by a query.

Basic Limit#

MATCH (u:User)
RETURN u.name
LIMIT 10

Limit with ORDER BY#

Get top N results:

MATCH (p:Post)
RETURN p.title, p.views
ORDER BY p.views DESC
LIMIT 10

Limit with Parameters#

MATCH (u:User)
RETURN u
LIMIT $maxResults

Python example:

graph.query("""
    MATCH (u:User)
    RETURN u
    LIMIT $limit
""", {'limit': 10})

SKIP and LIMIT (Pagination)#

Basic Pagination#

// Page 1 (skip 0, take 10)
MATCH (u:User)
RETURN u
ORDER BY u.name
SKIP 0
LIMIT 10

// Page 2 (skip 10, take 10)
MATCH (u:User)
RETURN u
ORDER BY u.name
SKIP 10
LIMIT 10

// Page 3 (skip 20, take 10)
MATCH (u:User)
RETURN u
ORDER BY u.name
SKIP 20
LIMIT 10

Parameterized Pagination#

MATCH (u:User)
RETURN u
ORDER BY u.created DESC
SKIP $skip
LIMIT $limit

Python example:

def get_users_page(page, page_size):
    skip = (page - 1) * page_size
    return graph.query("""
        MATCH (u:User)
        RETURN u
        ORDER BY u.created DESC
        SKIP $skip
        LIMIT $limit
    """, {'skip': skip, 'limit': page_size})

# Get page 3 with 20 items per page
users = get_users_page(page=3, page_size=20)

Limit per Group#

Top N per Category#

MATCH (p:Post)-[:IN_CATEGORY]->(c:Category)
WITH c, p
ORDER BY p.likes DESC
RETURN c.name, collect(p.title)[0..5] AS topPosts

Latest N per User#

MATCH (u:User)-[:POSTED]->(p:Post)
WITH u, p
ORDER BY p.created DESC
RETURN u.name, collect(p.title)[0..10] AS recentPosts

Limit with Aggregations#

MATCH (u:User)-[:POSTED]->(p:Post)
RETURN u.name, count(p) AS posts
ORDER BY posts DESC
LIMIT 20

Random Sample#

Get random subset:

MATCH (u:User)
RETURN u
ORDER BY rand()
LIMIT 100

Limit Early for Performance#

// Good: Limit early
MATCH (u:User)
WHERE u.active = true
RETURN u
ORDER BY u.created DESC
LIMIT 100

// Then do expensive operations on limited set
WITH u
MATCH (u)-[:POSTED]->(p:Post)
RETURN u, count(p)

Common Patterns#

MATCH (p:Post)
RETURN p.title, p.likes
ORDER BY p.likes DESC
LIMIT 10

Latest 20 Posts#

MATCH (p:Post)
RETURN p.title, p.created
ORDER BY p.created DESC
LIMIT 20

First 50 Users#

MATCH (u:User)
RETURN u.name
ORDER BY u.created ASC
LIMIT 50

Sample 100 Random Items#

MATCH (n:Product)
RETURN n
ORDER BY rand()
LIMIT 100

Top 5 per Category#

MATCH (p:Product)-[:IN_CATEGORY]->(c:Category)
WITH c, p
ORDER BY p.sales DESC
WITH c, collect(p)[0..5] AS topProducts
RETURN c.name, topProducts

Infinite Scroll Implementation#

def get_feed(last_seen_id=None, limit=20):
    if last_seen_id:
        # Get posts after last seen
        query = """
            MATCH (p:Post)
            WHERE id(p) < $last_id
            RETURN p
            ORDER BY id(p) DESC
            LIMIT $limit
        """
        params = {'last_id': last_seen_id, 'limit': limit}
    else:
        # Get initial posts
        query = """
            MATCH (p:Post)
            RETURN p
            ORDER BY id(p) DESC
            LIMIT $limit
        """
        params = {'limit': limit}

    return graph.query(query, params)

Cursor-Based Pagination#

More efficient than SKIP for large offsets:

// First page
MATCH (p:Post)
RETURN p
ORDER BY p.created DESC, id(p) DESC
LIMIT 20

// Next page (using last item as cursor)
MATCH (p:Post)
WHERE p.created < $lastCreated 
   OR (p.created = $lastCreated AND id(p) < $lastId)
RETURN p
ORDER BY p.created DESC, id(p) DESC
LIMIT 20

LIMIT with DISTINCT#

MATCH (u:User)-[:KNOWS]-(friend)-[:KNOWS]-(fof)
RETURN DISTINCT fof.name
LIMIT 50

Limit Subquery Results#

MATCH (u:User)
RETURN u.name,
  [(u)-[:POSTED]->(p:Post) | p.title][0..5] AS recentPosts

Performance Tips#

  1. Always Use with ORDER BY ```cypher // Deterministic results ORDER BY u.created DESC LIMIT 10

// Non-deterministic (random 10) LIMIT 10 ```

  1. Use Cursor Pagination for Large Datasets ```cypher // Good: Cursor-based WHERE p.created < $cursor LIMIT 20

// Bad: SKIP for large offsets SKIP 100000 LIMIT 20 ```

  1. Limit Early in Query cypher // Good: Limit before expensive operations MATCH (u:User) ORDER BY u.created DESC LIMIT 100 WITH u MATCH (u)-[:POSTED]->(p) RETURN u, count(p)

  2. Use Indexes for ORDER BY + LIMIT ```cypher CREATE INDEX ON :Post(created)

// Fast with index MATCH (p:Post) ORDER BY p.created DESC LIMIT 10 ```

Count Total with Pagination#

MATCH (u:User)
WITH count(u) AS total, collect(u) AS users
RETURN total, 
       users[0..10] AS page

Or separate queries:

# Get total count
total = graph.query("MATCH (u:User) RETURN count(u) AS total")[0]['total']

# Get page
page = graph.query("""
    MATCH (u:User)
    RETURN u
    SKIP $skip LIMIT $limit
""", {'skip': 0, 'limit': 10})

print(f"Showing 10 of {total} users")

Next Steps#