Select to view content in your preferred language

Attribute rule for maintaining many-to-many relationships

283
3
03-20-2026 05:39 AM
CarstenAndersson
Regular Contributor

I have two polygon feature classes, Municipality and District. There is a many-to-many relationship between the two, and therefore an intermediate table called Municipality_District_Rel. The relationships are automatically handled with attribute rules, based on a municipality must overlap a district with 80% or more for them to be related. And if a municipality cover less than 80% percent, the relationship has to be deleted.

The Arcade expression is:

// Arrays to store edits
var edits = [];
var adds = [];
var deletes = [];

// Get all District features
var allDistricts = FeatureSetByName($datastore, "District");

// Find District features that intersect this Municipality feature
var intersectingDistricts = Intersects(allDistricts, $feature);

// Determine which District features that this Municipality overlaps with 80% or more
var overlappingDistrictGlobalIds = [];
for (var district in intersectingDistricts) {
    var districtGeometry = Geometry(district);
    var districtArea = Area(districtGeometry);
    var intersectionGeometry = Intersection(Geometry($feature), districtGeometry);
    var intersectionArea = Area(intersectionGeometry);
    if ((intersectionArea / districtArea) >= 0.8) {
        // This district overlaps, so store the GlobalID for it
        Push(overlappingDistrictGlobalIds, district.GlobalID);
    }
}

// Determine which relationships to add (new District features that overlaps with at least 80%)
var relatedDistricts = FeatureSetByRelationshipName($feature, "Municipality_District_Rel", ["GlobalID"]);
for (var index in overlappingDistrictGlobalIds) {
    var districtGlobalId = overlappingDistrictGlobalIds[index];
    Console(districtGlobalId);
    var relatedDistrict = First(Filter(relatedDistricts, "GlobalID = '" + districtGlobalId + "'"));
    if (relatedDistrict == null) {
        // A relationship didn't exist, so add it
        Push(adds, {
            'attributes': {
                'Municipality_GlobalID': $feature.GlobalID,
                'District_GlobalID': districtGlobalId
            }
        });
    }
}

// Get existing relationships between Municipality and District features
var allRelationships = FeatureSetByName($datastore, "Municipality_District_Rel", ["*"]);
var relationships = Filter(allRelationships, "Municipality_GlobalID = '" + $feature.GlobalID + "'");

// Determine which relationships to delete (no longer overlapping with at least 80%)
for (var relationship in relationships) {
	if (!Includes(overlappingDistrictGlobalIds, relationship.District_GlobalID)) {
		// No longer overlapping enough, so delete the relationship
		Push(deletes, {'GlobalID': relationship.GlobalID});
	}
}

// Return edits dictionary if there are changes to the relatio
if (Count(adds) > 0 || Count(deletes) > 0) {
    Push(edits, {
        'className': "Municipality_District_Rel",
        'adds': adds,
        'deletes': deletes
    });
    return {'edit': edits};
}

When I click Analyze I get:

Skærmbillede 2026-03-20 133343.png

But when I try to save the attribute rule I get this:

Skærmbillede 2026-03-20 133514.png

What am I doing wrong?

0 Kudos
3 Replies
MikeMillerGIS
Esri Frequent Contributor

Try this, my only guess is that adds or deletes is an empty array and maybe that is causing an issue

// Arrays to store edits
var edits = [];
var adds = [];
var deletes = [];

// Get all District features
var allDistricts = FeatureSetByName($datastore, "District");

// Find District features that intersect this Municipality feature
var intersectingDistricts = Intersects(allDistricts, $feature);

// Determine which District features that this Municipality overlaps with 80% or more
var overlappingDistrictGlobalIds = [];
for (var district in intersectingDistricts) {
    var districtGeometry = Geometry(district);
    var districtArea = Area(districtGeometry);
    var intersectionGeometry = Intersection(Geometry($feature), districtGeometry);
    var intersectionArea = Area(intersectionGeometry);
    if ((intersectionArea / districtArea) >= 0.8) {
        // This district overlaps, so store the GlobalID for it
        Push(overlappingDistrictGlobalIds, district.GlobalID);
    }
}

// Determine which relationships to add (new District features that overlaps with at least 80%)
var relatedDistricts = FeatureSetByRelationshipName($feature, "Municipality_District_Rel", ["GlobalID"]);
for (var index in overlappingDistrictGlobalIds) {
    var districtGlobalId = overlappingDistrictGlobalIds[index];
    Console(districtGlobalId);
    var relatedDistrict = First(Filter(relatedDistricts, "GlobalID = @districtGlobalId"));
    if (relatedDistrict == null) {
        // A relationship didn't exist, so add it
        Push(adds, {
            'attributes': {
                'Municipality_GlobalID': $feature.GlobalID,
                'District_GlobalID': districtGlobalId
            }
        });
    }
}

// Get existing relationships between Municipality and District features
var allRelationships = FeatureSetByName($datastore, "Municipality_District_Rel", ["*"]);
var relationships = Filter(allRelationships, "Municipality_GlobalID = '" + $feature.GlobalID + "'");

// Determine which relationships to delete (no longer overlapping with at least 80%)
for (var relationship in relationships) {
	if (!Includes(overlappingDistrictGlobalIds, relationship.District_GlobalID)) {
		// No longer overlapping enough, so delete the relationship
		Push(deletes, {'GlobalID': relationship.GlobalID});
	}
}

// Return edits dictionary if there are changes to the relatio
if (Count(adds) == 0 && Count(deletes) == 0) {
    return;
}
var edit_payload =  {
    'className': "Municipality_District_Rel",
}
if (Count(adds)){
    edit_payload['adds'] = adds
}
if (Count(deletes)){
    edit_payload['deletes'] = deletes
}

Push(edits, edit_payload);
return {
    'edit': edits
};
0 Kudos
CarstenAndersson
Regular Contributor

Thanks Mike,

but unfortunately I get the same error. My initial though was a version issue. I am using ArcGIS Pro 3.3, but I get the same error message on ArcGIS 3.5.

The line that causes the error is: var allRelationships = FeatureSetByName($datastore, "Municipality_District_Rel", ["*"]);

But, it's the only way I can think of to delete the existing relationships.

Could this be a bug?

0 Kudos
MikeMillerGIS
Esri Frequent Contributor

Could be, I never tried to work with a M:N in arcade.

0 Kudos