I have a feature layer with 3 values that exist in other layers that contain information that I want stored in the point layer. I need to run a spatial query when a new feature has been created to look up data in these other 2 layers & then record this data in the main point layer. How can you achieve this?
I managed to get it working in the end by deleting the fields in the point feature, creating them again to match the polygon features & then using those in the code. I'm now going to publish to the portal to see if the rules persist & it works as it does in the Pro Project
I was playing around so moved the data as a test so all in the same geodb. In my test above the field HighwaysOfficer for example was the same in both the point & polygon fc which worked fine. But as you can see in the schema below the point field names are on the left & the polygon names are on the right. I updated the code by returning the field name of the polygon feature at the end of the code but that doesn't work?
ok so I've had some success with the code below which I have added 3 times with 3 rules so that each field is working. The test polygon layer is in the same geodb but the 'real' data lives in 2 different geodb's. I tried to reference by name in the same manner but it says 'can't find the table'. I could move this data so that it all resides in the same geodb but then the data lives in those geodb's for a reason as it's done by datatype. I can't use the getfromportal as the data is sensitive - how can I get around this issue?
// load the other featureset var fs = FeatureSetByName($datastore, "EnvGIS.ENVMGR.Highway_Officer_AreasPoly") // get the first feature from fs that intersects the current $feature var f = First(Intersects(fs, $feature)) // abort if we didn't find something if(f == null) { return } // return the intersecting feature's value return f.HighwaysOfficer
Hmmm. I tested the rule again, and it works for me. Are you sure that the field "HWDataCollectionPoints.ElectoralArea" is editable?
Can you send me the two feature classes (export them into a new gdb or as shapefiles), either here or in a private message?
Both the polygon & the point features are manager connections & I looked at the design of both features & the field's that I'm interested in aren't set to Read Only so not sure why I'm getting the error saying 'Field is not Editable'
@JohannesLindner
Thanks for you explanation above. The code I'm using now is below where I have replaced the names of the fields as you said.
On line 5 I used the name of the Polygon feature
On line 11 & 19 I've used 'ElectoralArea' which is the field that I want to obtain the value from.
On line 14 & 20 I've used 'ElectoralArea' again.
I have the the field 'ElectoralArea' in the point fc which is blank & the values are contained within the polygon layer. When I create the attribute rule I set the field to ElectoralArea.
// field for the rule: empty // load the polygon feature class var polygons = FeatureSetByName($datastore, "Highways.HIGHWAYMGR.HWDataCollectionPoly") // get the first polygon that intersects this point var i_polygon = First(Intersects(polygons, $feature)) // get the responsible person var person = Iif(i_polygon == null, null, i_polygon.ElectoralArea) // get the polygon's name var name = Iif(i_polygon == null, null, i_polygon.ElectoralArea) // return return { result: {attributes: { ElectoralArea: person, ElectoralArea: name }} }
Sorry, I forgot to answer yesterday...
does all of the required data need to live within the same project/map service or can the code work with other layers that already exist on our enterprise server?
The data has to be in the same datastore for the FeaturesetByName() function. If you have data in your Portal, you can use that with the FeaturesetByPortalItem() function.
The arcade code can't find the name of the feature?
There's a space in the name ("Feature X"), which is not allowed for feature classes. You're probably trying to input the feature class's alias. You have to use the actual name.
I have a field in the point feature class with the same name as the field that I'm looking up in the other layer. I specified this field when creating the expression but do you need to specify it in the code?
Yes. The f.Field in my sample expressions was meant as a placeholder for the actual field names.
rather than intersecting I need to use 'contains within'.
It doesn't work that way around, which is also why you get null. This is the signature of Contains():
Contains(containerGeometry, insideFeatures)
It expects a geometry or feature as first argument and a featureset as second argument. You're supplying a featureset (the polygons) as first argument and a feature (the point) as second. And even if you do it the right way, it won't return any results, because a point can't contain a polygon. You have to use Intersects(), which is OK, because if a polygon contains a point, that point will intersect the polygon.
Therefore the query will need to be something like - when a point is created in this particular polygon look up these 2 values - the name of the person who is responsible for the polygon & the polygon area name. These 2 values will the populate the fields in the point class.
So the rule would look like this (mashup of my two previous examples, with more descriptive variable names)
// field for the rule: empty // load the polygon feature class var polygons = FeaturesetByName($datastore, "NameOfThePolygonFeatureClass") // get the first polygon that intersects this point var i_polygon = First(Intersects(polygons, $feature)) // get the responsible person var person = Iif(i_polygon == null, null, i_polygon.ResponsiblePeron) // get the polygon's name var name = Iif(i_polygon == null, null, i_polygon.PolygonName) // return return { result: {attributes: { ResponsiblePerson: person, PolygonName: name }} }
Things you have to change:
If I create a point & it saves it returns the value of Null
The name of the field is the same in both the point fc & the polygon. The value is blank in the point fc but I want it grab the value from the polygon class then return that value & save it in the point fc
Also does all of the required data need to live within the same project/map service or can the code work with other layers that already exist on our enterprise server?
@JohannesLindner - rather than intersecting I need to use 'contains within'. The source information are names of people which are polygons & we're creating points. Therefore the query will need to be something like - when a point is created in this particular polygon look up these 2 values - the name of the person who is responsible for the polygon & the polygon area name. These 2 values will the populate the fields in the point class.
That's the plan, yes.
ok thanks - the feature layer will exist as a layer on a webmap.
@JohannesLindner with the code above do I add that to the feature whilst in Pro then publish to our enterprise server?
Once published with the updated attribute info will the code then be active?
As @Alaind_Espaignet said, that's a very common use case for Attribute Rules.
A very basic Attribute rule for transferring a single value ( @Alaind_Espaignet scenario):
// Calculation Attribute Rule on the point fc // field: the field you want to fill // triggers: Insert(, Update) // load the other featureset var fs = FeaturesetByName($datastore, "NameOfTheFC") // get the first feature from fs that intersects the current $feature var f = First(Intersects(fs, $feature)) // abort if we didn't find something if(f == null) { return } // return the intersecting feature's value return f.Field
And for multiple fields ( @AndrewReynoldsDevon scenario):
// Calculation Attribute rule on the point fc // field: empty! // triggers: Insert(, Update) // load the other featuresets var fs1 = FeaturesetByName($datastore, "NameOfTheFirstFC") var fs2 = FeaturesetByName($datastore, "NameOfTheSecondFC") // get the first feature from fs1 that intersects the current $feature var f1 = First(Intersects(fs1, $feature)) // if there is no intersecting feature, use a default value, else use that feature's field value var value1 = Iif(f1 == null, null, f1.Field) // do the same for fs2 var f2 = First(Intersects(fs2, $feature)) var value2 = Iif(f2 == null, null, f2.Field) // return return { result: {attributes: { Field1: value1, Field2: value2 }} }
I think you can do that with attribute rules in PRO.
https://pro.arcgis.com/en/pro-app/latest/help/data/geodatabases/overview/an-overview-of-attribute-rules.htm
I have a similar need. Create a point feature in a Parcel, grab some info from the intersecting parcel and populate it in the new feature.
Les membres connectés peuvent publier, suivre les mises à jour, et plus encore. Nouveau ici ? Inscrivez-vous gratuitement.
Find useful guides, FAQs, and documents to help you navigate and make the most of Esri Community.