01 / 01Guide
Link objects together by key
This guide shows how to build a map that groups structs by a shared key. You will need this pattern often when you work with many-to-one relations.
Take the following entity relations as an example:
entity house { key id: integer; color: text;}entity street { key address: text;}entity street_house { key house; index street;}Here, every house is unique and belongs to one street, while one street can hold many houses. To write a query that returns all houses grouped by street, you want a signature like this:
query get_houses_by_street(): map<text, list<struct<house>>>The map uses the street address as its key, and each value is a list of house structs. A plain database query with the at-operator gives you no more than a list<(text, struct<house>)>:
val house_list: list<(text, struct<house>)> = street_house @* {} ( .street.address, .house.to_struct() );To turn this into a map, you can rely on Rell's annotations for aggregating results into collections. @group sets the value you group by, and @list or @set sets the type of collection the grouped values go into.
With these, the results come back in a more useful shape:
val house_streets: list<(text, list<struct<house>>)> = street_house @* {} ( @group .street.address, @list .house.to_struct() );@group instructs the ORM to group results by street address, and @list gathers every house on that street into one list.
You can go one step further and convert that result straight into a map with another Rell ORM annotation, @map:
val houses_by_street = house_streets @ {} ( @map $ );This is a second at-expression, this time applied to a collection. Placing @map in the what-clause makes each entry act as a map entry.
This approach lets the database query do the grouping efficiently and produces the map structure in fewer lines of code.