Chromia
Start Building

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:

rell
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:

rell
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>)>:

rell
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:

rell
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:

rell
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.

Written for this site from Chromia’s public course. Code samples are the course’s own.