Search code examples
projectionqueryingeventstoredb

Querying EventStoreDB with java API or HTTP API


I have been using the brilliant Event Store DB by brilliant Greg Young lately and its fine. But the documentation is awful, it's outdated, sometimes incorrect, and distributed through the website. Sometimes you have to lookup multiple non relevant pages to break the code behind documentation!

Anyway, not only the documentation, but also the Java API sucks and most of the times you have to use the HTTP API instead.

I have built my own Java API upon the HTTP API.

I have been struggling with the projections and I was able to create multiple projections (continuous, one time, transient) and it works just fine and the resulting streams are populated with the events emitted by projection.

So now, I know how should I create new projections which will create streams filled with my desired events filtered by the given criteria in the when clause

I also read in the documentation that we can do temporal queries on event store, but we should populate another read model by the help of Catch-up subscription and I am fine with that and know what CQRS is. I'm using MongoDB to create read models for reports.

The thing I'm having difficulties with is the temporal queries. I couldn't find any documentation around how should I do queries. But I guessed that I should first create a one-time projection for each query and I should emit the results to a new stream name "query-{id}". Then I immediately try to read events off of the new query stream, but it takes time to create the query stream and fill it with the resulting events. So my API for queries creates a projection and immediately asks for events on the resulting stream, but it gets 404 which means the projection has not started processing and producing new stream yet.

So, is there any way to pass event store a projection and ask it for the events?

One thing I understood was that there is no way actually to query the event store in real time, but we should create a projection which will create a stream and fill it with result and mean while we should keep asking whether the stream is created and whether the projection is done.

I create a new stream for each of my aggregates and everything just works fine. And I have a separate bounded context for the reporting of the whole system and it uses MongoDB and that works fine to. But sometimes I need to query the events to check invariants. For example I need to check whether the "Product" title is unique or not and throw exception. In order to do such check, I should create a separate read model for aggregates inside each bounded context. But I want to do such queries simply by asking the event store for all "ProductCreated" events with the same title and then I want to process all those events to see if we have got a Product with the same title.

So how could I ask the event store for all ProductCreated events where title equals some value and get the result immediately?

Or maybe event store db is not designed for such usecases?!


Solution

  • Sorry to hear about your experience with the documentation. I am not sure if you noticed, but we published the new docs a couple of weeks ago and the old docs website clearly states in the banner that it's obsolete.

    The JVM client (not Java client) is not made by Event Store. The new client is being worked on right now but it's 20.6 client and will only support gRPC.

    There are quite a few things in your question, and I am not sure I understand all of it. It would be great to separate questions, if possible.

    I can reply to the one I understand, about reading events of the same type. The system by event type projection produces streams that you might be willing to read from ($et-ProductCreated in your example), but I am not sure if it solves your use-case since you might also have events like ProductRenamed and you'd need to handle it too.

    I won't really see this case as an "invariant" since your system would unlikely become inconsistent if two products accidentally get the same title. It depends on the number of products you expect to be registered and renamed simultaneously in the system. If you have new products being registered with a speed of 100 products per second, you probably won't be able to read all ProductCreated events anyway to find out if the new name is a duplicate of another. If you have like one product per hour, having a simple projection to MongoDB would be the easiest and fastest way to check for duplicates.

    I'd suggest opening another question concerning temporal queries.