LearnYour First Relationship

Your First Relationship

Continuing the concert app: a relationship is a directed edge between entity types — stored in a dedicated relationship store. Here, a user follows an artist.

Project: Concert app from causet init. Open relationships/follow.relationships.causet.

Prerequisite: Your First Stateuser and artist entities. The follow events from Your First Event drive projections and the ledger.


Declare the relationship

# relationships/follow.relationships.causet
relationships:
  artist_followers:
    from: user
    to:   artist
    cardinality: many_to_many
    unique: true
    emit_events:
      created: ARTIST_FOLLOWED
      removed: ARTIST_UNFOLLOWED
FieldPurpose
from / toEntity types at each end
cardinalitymany_to_many — users follow many artists
uniqueDuplicate follows are no-ops (idempotent retries)
emit_eventsEngine emits follow/unfollow events when edges change

When emit_events is set, the engine emits ARTIST_FOLLOWED / ARTIST_UNFOLLOWED — the same events your projections already consume.


Create edges from an intent

Use relationship_create in core rules (optional enhancement to FOLLOW_ARTIST):

# actions/follow.actions.causet  (core rule addition)
core:
  rules:
    - name: increment_following
      when: {}
      then:
        - op: add
          path: /following_count
          value: 1
        - op: relationship_create
          relationship: artist_followers
          from_id: intent.user_id
          to_id:   intent.artist_id

You can keep the explicit emit in side_effects or rely on emit_events on the relationship — not both for the same edge unless you need extra payload fields on the event.


Submit via CLI

Same command as Your First Intent:

causet intent FOLLOW_ARTIST \
  --fork main \
  --stream user_stream \
  --entity user-1 \
  --payload '{"user_id":"user-1","artist_id":"artist-pearl-jam"}'

The edge lands in the relationship store; the event feeds user_following; the query returns shows for followed artists.


When to use relationships vs projections alone

RelationshipsProjections only
Graph semantics, uniqueness, inverse traversalEvent-derived read tables
Engine-managed edge lifecycleAnything queryable from events

In this app, the relationship and user_following projection work together — the relationship enforces graph rules; the projection powers the join query.


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
  queries/        follow.queries.causet
  relationships/  follow.relationships.causet

Next steps