Relations and repeat observations
Outcome: create and test a GeoPackage relation connecting one stable monitoring site to many observation records.
A common GIS mistake is to create a new point every time somebody revisits the same site. A better model separates the site from visits.
monitoring_site
site_id
geometry
|
| 1 : many
v
observations
observation_id
site_id
observed_at
condition
Create the tables
In a GeoPackage use:
monitoring_sites — point geometry, one row per stable site
observations — no geometry required, many rows per site
Use text IDs that remain stable across exports.
Define the relation
Open Project → Properties → Relations and add a relation:
- referenced/parent layer: monitoring sites
- parent field:
site_id - referencing/child layer: observations
- child field:
site_id
Give the relation a descriptive ID/name.
Use forms
With a relation configured, a site form can display its related observation records. This is useful for repeat taiao monitoring, marae asset inspections and historical evidence tables.
Do not force one-to-many into a join
A normal QGIS layer join is one-to-one in practice. If a site has 20 visits, the data model should contain 20 child rows rather than 20 copies of the point or 20 date columns.
Exercise
This exercise creates one point layer, creates a small teaching table and connects them. Allow about 15 minutes. The records below are synthetic and exist only to demonstrate the relation.
Use these two monitoring sites:
| site_id | restoration_id | site_type | status | notes |
|---|---|---|---|---|
| SITE-001 | REST-001 | repeat_photo | active | Synthetic example |
| SITE-002 | REST-002 | condition_check | active | Synthetic example |
Create these initial child observations:
| observation_id | site_id | observed_at | condition_category | notes |
|---|---|---|---|---|
| OBS-001 | SITE-001 | 2026-02-14 10:00 | baseline | Synthetic example |
| OBS-002 | SITE-001 | 2026-08-12 10:00 | follow_up | Synthetic example |
1. Create the GeoPackage
- Open a new QGIS project.
- Set the project CRS to NZGD2000 / New Zealand Transverse Mercator 2000 (EPSG:2193).
- Choose Layer → Create Layer → New GeoPackage Layer.
- Browse to a working folder and create
awa-relations.gpkg. - Set Table name to
monitoring_sitesand Geometry type toPoint. - Add these text fields:
site_id,restoration_id,site_type,statusandnotes. - Click OK.
2. Add the two teaching sites
- Select
monitoring_sitesin the Layers panel and click Toggle Editing. - Click Add Point Feature and place a point anywhere in the map canvas.
- Enter the
SITE-001values from the table above. - Add a second point using the
SITE-002values. - Save the edits and turn editing off.
The point locations are arbitrary teaching geometry. Do not interpret them as real monitoring sites.
3. Create the observations table
- Choose Layer → Create Layer → New GeoPackage Layer.
- Select
awa-relations.gpkg. - Set Table name to
observationsand Geometry type toNo geometry. - Add fields for
observation_id,site_id,observed_at,condition_categoryandnotes. - Add the two observation rows shown above.
- Save the edits.
4. Define the relation
- Choose Project → Properties → Relations.
- Click Add Relation.
- Set the name and ID to
site_observations. - Set Referenced (parent) layer to
monitoring_sitesand its field tosite_id. - Set Referencing (child) layer to
observationsand its field tosite_id. - Click OK, then Apply and OK.
5. Confirm it works
- Select
monitoring_sitesand use Identify Features to click theSITE-001point. - Open its feature form if it is not already displayed.
- Find the
site_observationsrelated-record section. It should containOBS-001andOBS-002. - Add a child observation with a new unique ID such as
OBS-003, setsite_idtoSITE-001, and save it. - Reopen the site form and confirm that three observations now appear while the parent point remains a single feature.
If no records appear, compare the site_id values exactly. Spaces, different capitalisation or a missing ID will prevent the match.
Check
- parent IDs are unique
- every child
site_idexists in the parent table or is deliberately flagged unmatched - visit date/time is stored as a proper field
- deleting a site is handled cautiously because child records may remain
See the Awa restoration worked example for the same stable-site/repeat-observation pattern in a fuller project.
Next: Models and batch processing.
Official reference: QGIS joins and relations.
Last reviewed: 3 September 2026