Skip to main content

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_idrestoration_idsite_typestatusnotes
SITE-001REST-001repeat_photoactiveSynthetic example
SITE-002REST-002condition_checkactiveSynthetic example

Create these initial child observations:

observation_idsite_idobserved_atcondition_categorynotes
OBS-001SITE-0012026-02-14 10:00baselineSynthetic example
OBS-002SITE-0012026-08-12 10:00follow_upSynthetic example

1. Create the GeoPackage

  1. Open a new QGIS project.
  2. Set the project CRS to NZGD2000 / New Zealand Transverse Mercator 2000 (EPSG:2193).
  3. Choose Layer → Create Layer → New GeoPackage Layer.
  4. Browse to a working folder and create awa-relations.gpkg.
  5. Set Table name to monitoring_sites and Geometry type to Point.
  6. Add these text fields: site_id, restoration_id, site_type, status and notes.
  7. Click OK.

2. Add the two teaching sites

  1. Select monitoring_sites in the Layers panel and click Toggle Editing.
  2. Click Add Point Feature and place a point anywhere in the map canvas.
  3. Enter the SITE-001 values from the table above.
  4. Add a second point using the SITE-002 values.
  5. 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

  1. Choose Layer → Create Layer → New GeoPackage Layer.
  2. Select awa-relations.gpkg.
  3. Set Table name to observations and Geometry type to No geometry.
  4. Add fields for observation_id, site_id, observed_at, condition_category and notes.
  5. Add the two observation rows shown above.
  6. Save the edits.

4. Define the relation

  1. Choose Project → Properties → Relations.
  2. Click Add Relation.
  3. Set the name and ID to site_observations.
  4. Set Referenced (parent) layer to monitoring_sites and its field to site_id.
  5. Set Referencing (child) layer to observations and its field to site_id.
  6. Click OK, then Apply and OK.

5. Confirm it works

  1. Select monitoring_sites and use Identify Features to click the SITE-001 point.
  2. Open its feature form if it is not already displayed.
  3. Find the site_observations related-record section. It should contain OBS-001 and OBS-002.
  4. Add a child observation with a new unique ID such as OBS-003, set site_id to SITE-001, and save it.
  5. 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_id exists 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