Your First Projection
Continuing the concert app: projections are PostgreSQL read models maintained from events by the projection worker. You declare them in DSL, compile to causet.projections.json, and deploy with your release.
Project: Concert app from causet init. Open projections/follow.projections.causet.
Prerequisite: Your First Intent — emits ARTIST_FOLLOWED and SHOW_ANNOUNCED.
What projections do
Intent → Event on ledger → Kafka → Projection worker → UPSERT into tableEntity snapshots answer “what is user-1’s following_count?” Projections answer “which artists does user-1 follow?” and “what shows has Pearl Jam announced?”
Declare projections
Always declare fields: with explicit types.
# projections/follow.projections.causet
projections:
user_following:
source_events: [ARTIST_FOLLOWED, ARTIST_UNFOLLOWED]
target:
table: user_following
primary_key: [user_id, artist_id]
fields:
user_id: TEXT
artist_id: TEXT
followed_at: BIGINT
derive:
user_id: event.user_id
artist_id: event.artist_id
followed_at: event.ts
mutations:
ARTIST_FOLLOWED: { op: upsert }
ARTIST_UNFOLLOWED: { op: delete }
artist_show_directory:
source_events: [SHOW_ANNOUNCED]
target:
table: artist_show_directory
primary_key: [show_id]
fields:
show_id: TEXT
artist_id: TEXT
title: TEXT
venue: TEXT
date: TEXT
created_at: BIGINT
derive:
show_id: event.show_id
artist_id: event.artist_id
title: event.title
venue: event.venue
date: event.date
created_at: event.ts
mutations:
SHOW_ANNOUNCED: { op: upsert }| Projection | Fed by | Purpose |
|---|---|---|
user_following | Follow/unfollow events | Who each user follows |
artist_show_directory | Show announcements | All announced shows |
Compile and deploy
cd concert-app
causet build validate --runtime .
causet build compile --runtime . --out dist/
causet release create --input dist/ --tag 1.0.0
causet release publish --tag 1.0.0
causet deploy apply --tag 1.0.0 --fork main
causet deploy activate --tag 1.0.0 --fork main --mode FULLDeploy creates tables user_following and artist_show_directory in your fork schema.
Verify materialization
- Run
FOLLOW_ARTISTandANNOUNCE_SHOWfrom Your First Intent - Wait a few seconds for the projection worker
- Run the query in Your First Query
Control plane Projections page shows table health and row counts.
Concert app so far
concert-app/
app.causet
states/ user.state.causet, artist.state.causet
events/ follow.events.causet, show.events.causet
actions/ follow.actions.causet, show.actions.causet
projections/ follow.projections.causetNext steps
- Your First Query — join both tables
- Projections — derive, aggregates, indexes