Intersect vs iterate when getting attributes from another feature class

638
2
Jump to solution
10-13-2021 03:38 AM
AGP
by
Occasional Contributor

I need to calculate a number of fields in a feature class based on an intersecting polygon feature class. I'm using AGPro 2.4 so for every field calculation I must create a different attribute rule.

One of the fields I will retrieve from that one polygon feature class is the Id field (which I know is unique) so using intersect is not the only way to get the value from every field. Rule 1 could use intersect to get the value from the Id field and the following rules would iterate through the feature class to find the feature with matching Id field to get the value from the rest of fields.

The question is, what's the best option for better performance? All this will be published to Portal 10.7.1.

 

0 Kudos
1 Solution

Accepted Solutions
JohannesLindner
MVP Frequent Contributor

I guess you know already, but just to be sure: In Pro 2.7 and later, you can alter multiple attributes with the same rule, so upgrading would be your best option.

 

You outlined 2 possibilities:

  • doing the intersect in each rule
  • doing the intersect in the first rule, saving the id in a field, then using that id to filter (Filter(), you don't need to iterate) the target featureset

I don't know which one is faster, but my guess would be the second one, because the test for intersection should be more expensive than an sql query. Test it, I guess...

 

But I want to propose another solution:

Create a field that stores a string. In the first rule, you save the intersected feature's attributes in that field:

var fs = FeatureSetByName(.....)
var intersect_fs = Intersects($feature, fs)
var intersect_f = First(intersect_fs)

if(intersect_f == null) { return null } // no intersecting feature

var attributes = Dictionary(Text(intersect_f)).attributes
return Text(attributes)

 

In the following rules, you can use that field to extract the values:

if(IsEmpty($feature.IntersectAttributes)) { return null }

var attributes = Dictionary($feature.IntersectAttributes)
return attributes.Attribute

 

This way, you need to search the other table only once, which should be the best option performance-wise. You'd need to create an extra field, but you need that in your second proposed solution, too.


Have a great day!
Johannes

View solution in original post

2 Replies
JohannesLindner
MVP Frequent Contributor

I guess you know already, but just to be sure: In Pro 2.7 and later, you can alter multiple attributes with the same rule, so upgrading would be your best option.

 

You outlined 2 possibilities:

  • doing the intersect in each rule
  • doing the intersect in the first rule, saving the id in a field, then using that id to filter (Filter(), you don't need to iterate) the target featureset

I don't know which one is faster, but my guess would be the second one, because the test for intersection should be more expensive than an sql query. Test it, I guess...

 

But I want to propose another solution:

Create a field that stores a string. In the first rule, you save the intersected feature's attributes in that field:

var fs = FeatureSetByName(.....)
var intersect_fs = Intersects($feature, fs)
var intersect_f = First(intersect_fs)

if(intersect_f == null) { return null } // no intersecting feature

var attributes = Dictionary(Text(intersect_f)).attributes
return Text(attributes)

 

In the following rules, you can use that field to extract the values:

if(IsEmpty($feature.IntersectAttributes)) { return null }

var attributes = Dictionary($feature.IntersectAttributes)
return attributes.Attribute

 

This way, you need to search the other table only once, which should be the best option performance-wise. You'd need to create an extra field, but you need that in your second proposed solution, too.


Have a great day!
Johannes
AGP
by
Occasional Contributor

Unfortunately altering the field structure of the feature class is not an option. I'm saving the id in an existing field. That's one of the fields I'm asked to retrieve and I wanted to take advantage of that to get a better option, performance-wise, to calculate the rest of fields.

I will take a look at the Filter function though. Thanks!

0 Kudos