nenu-lang / joins
Stable

Joins

  • Joins always return an array of typed row objects.
  • Each joined entity appears under a lower-camel alias such as row.expense or row.room.
  • Lookup fields on both sides must satisfy the documented unique or index requirements.

Basic Join

code
1need rows = Expense[]({2  room_id == request.room_id3}) join Room(room_id)

For each left-side expense, Room(room_id) joins the room whose system identity matches the expense row’s room_id. The left query remains an array because joins produce row arrays.

Joined Row Shape

code
1loop rows as row {2  expense_amount = row.expense.amount3  room_name = row.room.name4}

The result is not a flat entity array. Each row contains lower-camel aliases derived from the participating entity names. Use row.expense and row.room before accessing their fields.

Join Forms

FormMeaning
join Room(room_id)Shorthand for joining Room system id to the left row’s room_id.
join Room.name(room_name)Shorthand for a named-field join. The named field must satisfy lookup rules.
join Room({ name == room_name })Explicit filter form.
A join after child fetch syntaxJoin from rows produced by a child entity read.

Index And Uniqueness Rules

  • Joins use an array result shape.
  • Left-side query fields must be @unique, @index, or system id where the join contract requires indexed lookup.
  • The right-side join field must be @unique, @index, or system id.
  • An exact left lookup by a named field must use @unique.
  • A child parent lookup by a named field must also be unique so one lookup value identifies one parent.

Join And Window Semantics

Join Values Are Row Paths

A right-side join filter such as room_id is a path on the current left row. It is not another need binding and therefore does not create a need dependency edge.

code
1need {2  expenses = Expense[]({ room_id == room.id })3  room = Room(request.room_id)4}

Common Mistakes

WrongCorrect
Expect row.amountUse row.expense.amount.
Use singular left resultUse Entity[](...) for a join.
Join unindexed arbitrary fieldsAdd the appropriate unique or index contract.
Treat join row paths as need bindingsRead them as fields from each left row.

Continue Learning