Skip to content

Running EventQL Queries

This guide shows how to query events using EventQL – the query language built into EventSourcingDB. You'll learn how to run your first queries and understand when using EventQL makes sense.

Why Use EventQL?

When working with EventSourcingDB, you typically read events by subject. That works well when you're interested in the full history of a single entity – like a book or a reader.

But sometimes you want to ask different questions:

  • What are all the events in the system?
  • How many times was a book borrowed?
  • Which event types have occurred so far?

To answer these questions, EventQL offers a flexible way to filter, sort, and aggregate events on the server side – using a syntax that is inspired by SQL but tailored for event data. Unlike SQL, EventQL works with nested structures, streams results as they are processed, and reflects the temporal nature of event-based systems.

Running a Basic Query

To run a query, send a POST request to the /api/v1/run-eventql-query endpoint and pass the query as a string. For example, the following query returns all events in the database:

FROM e IN events
PROJECT INTO e

You can execute this query using curl:

curl \
  -i \
  -X POST \
  -H "authorization: Bearer <API_TOKEN>" \
  -H "content-type: application/json" \
  -d "{
    \"query\": \"FROM e IN events PROJECT INTO e\"
  }" \
  http://localhost:3000/api/v1/run-eventql-query

This will return all events, one per line, in the order they were written.

Listing the Most Recent Events

If you're interested in the most recent events – regardless of their type or subject – you can sort them in descending order and limit the result:

FROM e IN events
ORDER BY e.time DESC
TOP 100
PROJECT INTO e

This query returns the 100 latest events in reverse chronological order.

Filtering by Type

You can filter events by type to narrow down your results. For example, to find all events where a book was acquired:

FROM e IN events
WHERE e.type == "io.eventsourcingdb.library.book-acquired"
PROJECT INTO { id: e.id, title: e.data.title }

This returns each event's ID and the acquired book's title.

Filtering by Subject

You can also filter events for a specific subject. The result is similar to what you'd get from the /read-events endpoint, but you have full control over the output format:

FROM e IN events
WHERE e.subject == "/books/42"
PROJECT INTO e

This returns all events that belong to the book with ID 42.

Counting Events

If you're only interested in how many events match a condition, you can use the COUNT() function:

FROM e IN events
WHERE e.type == "io.eventsourcingdb.library.book-borrowed"
PROJECT INTO { total: COUNT() }

This query tells you how often books have been borrowed.

Grouping by Type

To count how many events exist for each event type, use grouping and aggregation:

FROM e IN events
GROUP BY e.type
PROJECT INTO { type: UNIQUE(e.type), count: COUNT() }

This groups all events by type and counts how many times each type occurred.

Understanding the Result

The result is returned in NDJSON format – one line per result. Each line contains the projected data, exactly as specified in your PROJECT INTO clause. This is the same output format as when reading or observing events.

Your Turn

Try running a few queries on the events you've already written:

  • Show all events for the system.
  • Display the 10 most recent events.
  • Filter all book borrowed events for a specific book.
  • Count how many events exist for a reader.
  • Group events by type and show the number of occurrences.

To explore more advanced features, including subqueries, functions, and type conversions, see the EventQL reference.