Select to view content in your preferred language

Need to pull the proper Facility Name from one of 3 related records

218
3
03-26-2025 12:46 PM
JoshEisenfeld
New Contributor

I am working on a field maps form for a group of field inspectors who inspect 3 types of facilities. Each facility is stored in our map as seperate layers though they have (mostly) the same fields with some slight changes between the three for different info needs. The important thing is that they all have the same "FAC_ID" field. I am trying to have our form autopopulate the "Facility Name" line to avoid human error. The field to pull from is "FAC_NAME" for two of the related records and the other uses "LEASE_NAME". I created an expression to pull all three, create a new dictionary and turn that back into a feature service. See below:

var facilityfs = FeatureSetByRelationshipName($feature, "TX_ALL_FACILITIES", ['FAC_NAME', 'FAC_ID'], false)
var wellfs = FeatureSetByRelationshipName($feature, "TX_GMH_OILGAS_WELLS", ['LEASE_NAME','FAC_ID'], false)
var pipelinfs = FeatureSetByRelationshipName($feature, "TX_PIPELINE_POINTS_ALL", ['FAC_NAME', 'FAC_ID'], false)

// Create empty feature array and feat object for output
var features = [];
var feat;

// Iterate facilityfs
for (var f in facilityfs) {

    // Create feature with aggregated values
    feat = { 
      'attributes': { 
        'FACILITYID': f['FAC_ID'],
        'FACILITYNAME': f['FAC_NAME']
        }
    };
    
    // Push feature into array
    Push(features, feat);
};

// Iterate wellfs
for (var w in wellfs) {

    // Create feature with aggregated values
    feat = { 
      'attributes': { 
          'FACILITYID': w['FAC_ID'],
          'FACILITYNAME': w['LEASE_NAME']
        }
    };
    
    // Push feature into array
    Push(features, feat);
};

// Iterate pipelinefs
for (var p in pipelinfs) {
    
    // Create feature with aggregated values
    feat = { 
      'attributes': { 
          'FACILITYID': p['FAC_ID'],
          'FACILITYNAME': p['FAC_NAME']
        }
    };
    
    // Push feature into array
    Push(features, feat);
};

// Create dict for output FeatureSet
var out_dict = { 
    'fields': [
        {'name': 'FACILITYID', 'type': 'esriFieldTypeString'},
        {'name': 'FACILITYNAME', 'type': 'esriFieldTypeString'},
    ],
    geometryType: '',
    'features': features 
}; 

// Convert dictionary to feature set. 
var allfs = FeatureSet(Text(out_dict))


return allfs

 

The code works but it only gives me one result (which seems odd but I'm new)

Screenshot 2025-03-26 at 3.40.59 PM.png

And so I tried to move on to the next step (I think) which would be to pull from matching FAC_IDs (now FACILITYID in the combined fs) to return the FACILITYNAME in the combined fs. So I take out the return allfs and replace it with this:

if (!IsEmpty(allfs)) {
    return allfs['FACILITYNAME']
} else {
    return null
}

 

And I get this error:

"Test execution error: Execution error - Cannot access value using a key of this type. Verify test data."

 

I have tried looking around for similar situations but I have not found a solution. Does anyone know where I messed up? Any help would be greatly appreciated!

 

0 Kudos
3 Replies
AustinAverill
Frequent Contributor

For diagnostic purposes, I would add a return as the first line in each loop to make sure that the item you are looping over is a feature array and not an index. Randomly, I will get loops like this where the loop value (var f in features) is an index value. Then I get test executions when I try to access the data in the form of `f['fieldName']`. 

Similarly, given your end goal, I think you might be over complicating this a bit by trying to create one master list of names and id's. You could simply filter each array and return the value if it exists in the table. Something like below. This eliminates the headache of trying to concatenate multiple data sets and doesn't expose your data to any unintentional transformations.

var facilityfs = FeatureSetByRelationshipName($feature, "TX_ALL_FACILITIES", ['FAC_NAME', 'FAC_ID'], false);
var wellfs = FeatureSetByRelationshipName($feature, "TX_GMH_OILGAS_WELLS", ['LEASE_NAME','FAC_ID'], false);
var pipelinfs = FeatureSetByRelationshipName($feature, "TX_PIPELINE_POINTS_ALL", ['FAC_NAME', 'FAC_ID'], false);

var argg = $feature.FAC_ID
var query = "FAC_ID = @argg"

if(Count(Filter(facilityfs, query)) == 1){
    return First(Filter(facilityfs, query))['FAC_NAME']
}

//repeat for other feature layers

 

0 Kudos
RPGIS
by MVP Regular Contributor
MVP Regular Contributor

To add to @AustinAverill.

If the facilities are identical/share a common location, then your code will only return one facility. If there are multiple facilities and you are trying to only determine the feature's facility that it corresponds with, then the code you have writing would be overly complicated for the implementation.

With that being said, if you are looking to identify which facility a feature should belong to given certain criteria then that would have a different result than the one you are looking for. A simpler way to get a list of all facilities and identify the likeliest candidate would look like the code below.

function GetFacilityName( InFeature , FieldName , FilterValue , AcquireField, DictOfValues ){
	var Value = Filter( InFeature , FieldName + ' = @FilterValue' )
	if( !IsEmpty( Value ) ){ Value = First( Value )[ AcquireField ] }
	
	var TValue = Text( FilterValue )
	if( TypeOf( DictOfValues ) == 'Dict' && HasKey( DictOfValues , TValue ) ){ Push( DictOfValues[ TValue ] , Value ) }
	else{ DictOfValues = Dictionary( TValue , [ Value ] ) }
	return DictOfValues
	}

var facilityfs = FeatureSetByRelationshipName($feature, "TX_ALL_FACILITIES", ['FAC_NAME', 'FAC_ID'], false)
var wellfs = FeatureSetByRelationshipName($feature, "TX_GMH_OILGAS_WELLS", ['LEASE_NAME','FAC_ID'], false)
var pipelinfs = FeatureSetByRelationshipName($feature, "TX_PIPELINE_POINTS_ALL", ['FAC_NAME', 'FAC_ID'], false)

var FacilID = $feature.FAC_ID
var FacilName = GetFacilityName( facilityfs, 'FAC_ID', FacilID, 'FAC_NAME', None )
FacilName = GetFacilityName( wellfs, 'FAC_ID', FacilID, 'LEASE_NAME', FacilName )
FacilName = GetFacilityName( pipelinfs, 'FAC_ID', FacilID, 'FAC_NAME', FacilName )

var Name = Null
var TID = Text( FacilID )
if( HasKey( FacilName , TID ) ){
	var Names = FacilName[ TID ]
	if( Count( Names ) > 1 ){ Console( '${ Names } has more than one associated facility' ) }
	else if( Count( Names ) == 1 ){ Name = Names[0] }
	else{ Console( 'No names match the given criteria' ) }
	}
return Name

Also, attribute rules can only populate a single attribute in a field that is selected/calculated by the rule. So, creating another feature would not meet the requirements to calculate that field.

0 Kudos
AustinAverill
Frequent Contributor

Ah. I might have misunderstood OP's objective here then. I was under the impression that the three tables all used the same format for FAC_ID and OP was trying to find a single value. I might have lost the plot here.

0 Kudos