home / skills / sstobo / convex-skills / convex-queries

convex-queries skill

/convex-queries

This skill guides you in implementing Convex query functions with indexing, pagination, and full-text search to improve data retrieval.

npx playbooks add skill sstobo/convex-skills --skill convex-queries

Review the files below or copy the command above to add this skill to your agents.

Files (2)
SKILL.md
3.6 KB
---
name: convex-queries
description: This skill should be used when implementing Convex query functions. It provides comprehensive guidelines for defining, registering, calling, and optimizing queries, including pagination, full text search, and indexing patterns.
---

# Convex Queries Skill

This skill provides specialized guidance for implementing Convex query functions, including best practices for function definition, registration, calling patterns, pagination, indexing, and full text search.

## When to Use This Skill

Use this skill when:
- Defining new query functions to fetch data from the Convex database
- Implementing pagination for large result sets
- Setting up indexes for efficient querying
- Using full text search functionality
- Calling queries from other Convex functions
- Optimizing query performance

## Skill Resources

This skill includes comprehensive reference documentation in `references/query-guidelines.md` that covers:

### Core Query Development
- Function definition syntax using the new function syntax
- Query registration (`query` and `internalQuery`)
- Argument validators and their usage
- Function calling patterns (`ctx.runQuery`)
- Function references (`api` and `internal` objects)
- File-based routing for query paths

### Query Optimization
- Query guidelines (avoiding `filter`, using indexes with `withIndex`)
- Ordering results with `.order('asc')` and `.order('desc')`
- Using `.unique()` for single document retrieval
- Async iteration with `for await` syntax
- Query limits and performance considerations

### Advanced Query Features
- **Pagination**: Implementing paginated queries with `paginationOptsValidator`
  - Understanding `paginationOpts` (numItems and cursor)
  - Reading paginated results (page, isDone, continueCursor)
- **Full Text Search**: Setting up and querying search indexes
- **Indexing**: Creating and using indexes for efficient lookups
  - Built-in indexes (by_id, by_creation_time)
  - Custom index naming and field ordering
  - Nested queries with multiple indexes

### Database Queries
- Reading from the Convex database with `ctx.db.query()`
- Index usage with `.withIndex()`
- Result collection with `.collect()` and `.take(n)`

## How to Use This Skill

1. **Read the reference documentation** at `references/query-guidelines.md` to understand the complete query patterns
2. **Follow the syntax examples** for defining query functions with proper validators
3. **Use indexes** for efficient filtering instead of the `filter` method
4. **Implement pagination** when dealing with large datasets
5. **Leverage full text search** for text-based filtering needs
6. **Optimize ordering** by understanding how Convex orders results

## Key Query Guidelines

- ALWAYS include argument validators for all query functions
- Do NOT use `filter` in queries; use `withIndex` instead
- Use `ctx.runQuery` to call queries from mutations or actions
- Specify return type annotations when calling queries in the same file (TypeScript circularity workaround)
- Queries execute for at most 1 second and can read up to 16384 documents
- Return `null` implicitly if your query doesn't have an explicit return value

## Example: Basic Query with Index

```ts
import { query } from "./_generated/server";
import { v } from "convex/values";

export const getMessagesByChannel = query({
  args: {
    channelId: v.id("channels"),
  },
  handler: async (ctx, args) => {
    return await ctx.db
      .query("messages")
      .withIndex("by_channel", (q) => q.eq("channelId", args.channelId))
      .order("desc")
      .take(20);
  },
});
```

For more detailed information and additional patterns, refer to the complete reference documentation.

Overview

This skill provides practical guidance for implementing Convex query functions. It covers defining and registering queries, calling patterns, pagination, full text search, and index strategies to keep queries efficient and predictable. Use it to standardize query behavior and optimize read performance.

How this skill works

The skill inspects common Convex query patterns and prescribes concrete handlers, validators, and calling conventions. It explains when to use ctx.db.query, how to attach indexes with withIndex, how to call queries from other functions via ctx.runQuery, and how to design paginated and full text search queries. It also highlights runtime limits and patterns to avoid slow operations.

When to use it

  • When defining new Convex query functions to fetch structured data
  • When implementing pagination for large result sets
  • When creating or using indexes for efficient lookups
  • When adding full text search or text filtering to queries
  • When calling queries from mutations, actions, or other queries
  • When optimizing query performance and ordering

Best practices

  • Always include argument validators for every query function to enforce inputs
  • Avoid client-side filtering; use withIndex and indexed conditions instead of filter
  • Use .order('asc'|'desc') and .take(n) or .collect() to bound result size
  • Implement pagination using pagination options (numItems and cursor) and return continueCursor/isDone
  • Use ctx.runQuery to invoke queries from mutations or actions and annotate return types in the same file when needed
  • Prefer .unique() for queries expected to return a single document and explicit null returns when appropriate

Example use cases

  • Fetch latest messages for a channel using a by_channel index and .order('desc').take(20)
  • Implement cursor-based pagination for feeds using paginationOpts and continueCursor
  • Create custom compound indexes for multi-field lookups and use withIndex to query them
  • Build a full text search index for message content and expose a search query that returns ranked results
  • Call query functions from a mutation using ctx.runQuery to reuse read logic and keep mutations thin

FAQ

What should I avoid when writing Convex queries?

Avoid using .filter for large result sets; prefer indexed queries with withIndex to stay within performance limits.

How do I paginate results reliably?

Accept pagination options (numItems and cursor), return a page array plus isDone and continueCursor, and use consistent ordering with an index for stable cursors.