Event Queries | laravel-event-sourcing | Spatie

 SPATIE

  Laravel Event Sourcing
=========================

spatie.be/open-source

  [Docs](https://spatie.be/docs)  [Laravel-event-sourcing](https://spatie.be/docs/laravel-event-sourcing/v7)  Advanced-usage  Event Queries

 Version   v7   v6   v5   v4   v3   v2   v1

 Other versions for crawler [v7](https://spatie.be/docs/laravel-event-sourcing/v7) [v6](https://spatie.be/docs/laravel-event-sourcing/v6) [v5](https://spatie.be/docs/laravel-event-sourcing/v5) [v4](https://spatie.be/docs/laravel-event-sourcing/v4) [v3](https://spatie.be/docs/laravel-event-sourcing/v3) [v2](https://spatie.be/docs/laravel-event-sourcing/v2) [v1](https://spatie.be/docs/laravel-event-sourcing/v1)

- [ Introduction ](https://spatie.be/docs/laravel-event-sourcing/v7/introduction)
- [ Support us ](https://spatie.be/docs/laravel-event-sourcing/v7/support-us)
- [ Requirements ](https://spatie.be/docs/laravel-event-sourcing/v7/requirements)
- [ Installation &amp; setup ](https://spatie.be/docs/laravel-event-sourcing/v7/installation-setup)
- [ Questions and issues ](https://spatie.be/docs/laravel-event-sourcing/v7/questions-issues)
- [ Changelog ](https://spatie.be/docs/laravel-event-sourcing/v7/changelog)
- [ Upgrading ](https://spatie.be/docs/laravel-event-sourcing/v7/upgrading)
- [ Resources and alternatives ](https://spatie.be/docs/laravel-event-sourcing/v7/resources-and-alternatives)
- [ About us ](https://spatie.be/docs/laravel-event-sourcing/v7/about-us)

Getting familiar with event sourcing
------------------------------------

- [ Introduction ](https://spatie.be/docs/laravel-event-sourcing/v7/getting-familiar-with-event-sourcing/introduction)
- [ The traditional application ](https://spatie.be/docs/laravel-event-sourcing/v7/getting-familiar-with-event-sourcing/the-traditional-application)
- [ Using projectors to transform events ](https://spatie.be/docs/laravel-event-sourcing/v7/getting-familiar-with-event-sourcing/using-projectors-to-transform-events)
- [ Using aggregates to make decisions based on the past ](https://spatie.be/docs/laravel-event-sourcing/v7/getting-familiar-with-event-sourcing/using-aggregates-to-make-decisions-based-on-the-past)

Using projectors
----------------

- [ Writing your first projector ](https://spatie.be/docs/laravel-event-sourcing/v7/using-projectors/writing-your-first-projector)
- [ Creating and registering projectors ](https://spatie.be/docs/laravel-event-sourcing/v7/using-projectors/creating-and-configuring-projectors)
- [ Making sure events get handled in the right order ](https://spatie.be/docs/laravel-event-sourcing/v7/using-projectors/making-sure-events-get-handled-in-the-right-order)
- [ Thinking in events ](https://spatie.be/docs/laravel-event-sourcing/v7/using-projectors/thinking-in-events)

Using reactors
--------------

- [ Writing your first reactor ](https://spatie.be/docs/laravel-event-sourcing/v7/using-reactors/writing-your-first-reactor)
- [ Creating and configuring reactors ](https://spatie.be/docs/laravel-event-sourcing/v7/using-reactors/creating-and-configuring-reactors)

Using aggregates
----------------

- [ Writing your first aggregate ](https://spatie.be/docs/laravel-event-sourcing/v7/using-aggregates/writing-your-first-aggregate)
- [ Creating and configuring aggregates ](https://spatie.be/docs/laravel-event-sourcing/v7/using-aggregates/creating-and-configuring-aggregates)
- [ Testing aggregates ](https://spatie.be/docs/laravel-event-sourcing/v7/using-aggregates/testing-aggregates)
- [ Snapshots ](https://spatie.be/docs/laravel-event-sourcing/v7/using-aggregates/snapshots)

Advanced usage
--------------

- [ Preparing events ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/preparing-events)
- [ Replaying events ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/replaying-events)
- [ Storing metadata ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/storing-metadata)
- [ Handling exceptions ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/handling-exceptions)
- [ Discovering projectors and reactors ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/discovering-projectors-and-reactors)
- [ Using your own event storage model ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/using-your-own-event-storage-model)
- [ Using your own event storage repository ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/using-your-own-event-storage-repository)
- [ Using your own event serializer ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/using-your-own-event-serializer)
- [ Using aliases for stored event classes ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/using-aliases-for-stored-event-classes)
- [ Adding and Removing Projectors and Reactors ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/adding-and-removing-projectors-and-reactors)
- [ Aggregate Partials ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/aggregate-partials)
- [ Event Queries ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/event-queries)
- [ Commands ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/commands)

 Event Queries
=============

###  On this page

1. [ Want to know more? ](#content-want-to-know-more)

Event queries are classes that represent in-memory projections. Whenever an event query is retrieved, it will query the relevant events from the database and apply them internally. These events may result in state that's exposed to the outside.

Note that event queries should only ever be used to read data, and never result in changes.

Here's an example of an event query that will query order events to determine how much a collection of products have earned over a given period of time:

```
namespace App\Reports;

use Illuminate\Support\Collection;
use Spatie\EventSourcing\EventHandlers\Projectors\EventQuery;
use Spatie\Period\Period;

class EarningsForProductAndPeriod extends EventQuery
{
    public function __construct(
        private Period $period,
        private Collection $products
    ) {
        // …
    }
}
```

The first step in implementing an event query is the determine which events should be applied, this is done by querying the events table, and applying every retrieved event. It's important to note that event queries are only a viable solution if you know you've got a limited data set to work with. For example: generating this report for a month or two should be fine, but if you're querying over a period of time that contains millions of events, you'll get in trouble.

Here's what the full constructor of our example query looks like:

```
// ...
use Spatie\EventSourcing\StoredEvents\Models\EloquentStoredEvent;

class EarningsForProductAndPeriod extends EventQuery
{
    public function __construct(
        private Period $period,
        private Collection $products
    ) {
        EloquentStoredEvent::query()
            // We're only interested in `OrderCreated` events
            ->whereEvent(OrderCreated::class)
            // And we only need events within a given period
            ->whereDate(
                'created_at', '>=', $this->period->getStart()
            )
            ->whereDate(
                'created_at', 'filter(function (OrderLineData $orderLineData) {
            return $this->products->first(
                fn(Product $product) =>$orderLineData->productEquals($product)
            ) !== null;
        })
        // We the price of the relevant lines together
        ->sum(
            fn(OrderLineData $orderLineData) => $orderLineData->totalPriceIncludingVat
        );

    // Finally, we increment our total price, the grand total of all relevant events
    $this->totalPrice += $totalPriceForOrder;
}
```

Finally, the only things left to do are exposing the state, and using our query:

```
class EarningsForProductAndPeriod extends EventQuery
{
    // …

    public function totalPrice(): int
    {
        return $this->totalPrice;
    }
}
```

```
$report = new EarningsForProductAndPeriod(
    Period::make('2021-01-01', '2021-02-01'),
    $collectionOfProducts,
);

$report->totalPrice();
```

Want to know more?
------------------------------------------------------------------------------------------------------------

Our course, [Event Sourcing in Laravel](https://event-sourcing-laravel.com/) covers event queries in depth:

- 7. Event Queries
