LearnYour First Projection

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 table

Entity 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 }
ProjectionFed byPurpose
user_followingFollow/unfollow eventsWho each user follows
artist_show_directoryShow announcementsAll 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 FULL

Deploy creates tables user_following and artist_show_directory in your fork schema.


Verify materialization

  1. Run FOLLOW_ARTIST and ANNOUNCE_SHOW from Your First Intent
  2. Wait a few seconds for the projection worker
  3. 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.causet

Next steps