Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add support for n-m relations #4252

@tomasMizera

Description

@tomasMizera

Due to an existing data model setup in PostgreSQL, we received a request to add support for N-M relations.

In QGIS, N-M relations are implemented on top of the existing 1-N relation system. When configured correctly, QGIS adjusts the feature form UI so that the intermediate association table is hidden from the user.

Parent (1) ------ (N) Association/Join table (N) ------- (1) Child

This behaviour is controlled by the Cardinality setting in the feature form. When the relations are configured as shown above, QGIS recognises the N-M pattern and skips the association table in the UI.

As a result, users see a simplified interface where one parent feature can have multiple children, and a single child can be associated with multiple parents, without interacting with the linking table directly:

Parent view Child view


Mergin Maps side of things

The same general approach used in QGIS could be implemented in Mergin Maps. In other words, the parent form’s relation widget would list features from the child layer directly - and the child layer would list its parents - while the association (join) table remains hidden from the UI.

At the moment, our mobile app hides the relation widget entirely whenever it detects an N-M setup. This happens on both the parent and child layers:

This behaviour is intentional:

bool isNmRelation = layer->editFormConfig().widgetConfig( associatedRelation.id() )[QStringLiteral( "nm-rel" )].toBool();
if ( isNmRelation )
{
CoreUtils::log( "Relations", QStringLiteral( "Nm relations are not supported in layer %1" ).arg( layer->name() ) );
continue;
}

To support N-M relations properly, the main change required is to adjust how we fetch related features from the referenced (child) layer.

Currently, RelationFeaturesModel retrieves related features like this:

QgsFeatureRequest e = mRelation.getRelatedFeaturesRequest( mParentFeatureLayerPair.feature() );

With N-M relations, the first call to getRelatedFeaturesRequest returns features from the association table, not directly from the child layer. Therefore, for each returned association-table feature, we need to perform an additional lookup - calling getRelatedFeaturesRequest (or the filter version) again - to retrieve the corresponding child features.

By merging these second-level results, we obtain the final list of child features to display in the relation widget. Essentially:

  1. Fetch rows from the association table.
  2. For each row, resolve the referenced child feature.
  3. Combine the results into a single list for the UI.

It is a bit more work under the hood, but conceptually straightforward - and it would allow us to support N-M relations in a way consistent with QGIS.

For example, this is how it is done in QGIS: https://github.com/qgis/QGIS/blob/c755c5864983ce5cbb7f47b22cbea17ff5a9bc75/src/gui/qgsrelationeditorwidget.cpp#L624-L650


You can find a demo project with n-m relations setup here: https://app.dev.merginmaps.com/projects/SurveyCorp/many-to-many-relation/tree

Next steps (to explore)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions