Select to view content in your preferred language

Creating near real-time updates using arcade.

363
4
02-18-2025 12:08 PM
RPGIS
by MVP Regular Contributor
MVP Regular Contributor
3 4 363

Here is the workflow that is utilized for creating near real-time updates along with some code snippets that makes editing more streamlined. This works for both features/tables created in enterprise sde databases and file geodatabases. The workflow works best when using published services from an enterprise sde database that are published to either AGO or an enterprise portal.

Create an attribute rule using the following code below.

 

 

/*
The function below updates the edit array depending on what kind of edits are
needing to be applied.The edits are based on the input dictionary of the type
of edit.
*/
function PopulateEditsArray( EditArray , OIDs , Values ){
    var Values = {}
    if( TypeOf( Values ) == 'Dictionary' ){ Values.attributes = Values }
    if( TypeOf( OIDs ) == 'Number' ){ Values.OBJECTID = OIDs }
    Push( EditArray , Values )
    return EditArray
    }
/*
The function below checks the values( dictionary ) and compares it to the input
feature( dictionary ) and checks for any changes. Returns true if any of the
values are not identical.
*/
function CheckDifferences( Infeature , CheckValues ){
    var Check = False
    for( var field in CheckValues ){
        if( HasKey( Infeature , Field ) && Infeature[ Field ] != CheckValues[ field ] ){ Check = True ; break }
        }
     return Check
     }
/*
The function below populates the edit array with the editing features and 
attributes of either tables and/or feature classes that will be updated by the
edit array.
*/
function FeatureEdits( EditFeature , TableName , Values ){
    var FeatureEdits = { className : TableName }
    var ApplyEdits = False
    for( var i in Values ){
        if( Count( Values[ i ] ) > 0 ){
            FeatureEdits[ i ] = Values[ i ]
            ApplyEdits = True
            }
        }
    if( ApplyEdits ){ Push( EditFeature.edit , FeatureEdits ) }
    return EditFeature
    }

/*
List of field names to be used or searched for in the given feature/table.
*/
var OIDField = 'OBJECTID'
var DateTimeField = '<DateTimeEField>'

/*
Expects pulls all information in a feature and is returned as a dictionary
of field names and attributes. Using the field names above, it is easier to 
independently reference a single field name than having to type the field
name multiple times. When used in conjunction with '$feature', the field name
variable can be used as bracket notation to get the attribute value.
*/
Expects( $feature , '*' )
var OID = $feature[ OIDField ]
var DateTimeValue = $feature[ DateTimeField ]
var Example = $feature['<otherfield>']

/*
When working with an enterprise sde database, the schema owner may be different
so by assigning the owner as a variable makes it easier for changing the owner
if copying the code to a different database. The variable for table or feature
names can be used in conjunction with the schema owner to get the complete table
name.
*/
var CharSep = '.'
var SchemaOwner = '<SchemaOwner>'
var TableOrFeature_Name = "<TableOrFeature_Name>"
/*
The dictionary below is populated, however needed but the setup below is the one
that I find easiest. Here is the breakdown of the dictionary that is populated
below.
	'FS'
		This the key for identifying the feature class/table that is being edited.
		The name has to be written fully. The table name cannot be referenced by avariable
	'Query'
		This is used to query the feature, if needed, to filter the data based on the query.
	'DefaultValues'
		This is used to compare values using the function 'CheckDifferences' that is intially created
You can add as many features as needed to the table set below as needed.
*/
var TableSets = {}
TableSets[ TableOrFeature_Name ] = {
    'FS' : FeatureSetByName( $datastore, "<TableOrFeature_Name>", [ <'Array of Field Names'> ] ),
    'Query' : OIDField + ' = @OID',
    'DefaultValues' : Dictionary( DateTimeField , DateTimeValue )
    }

//Repeat the same setup as above for multiple tables.

/*
Set any required condition to apply the edit to the feature. Not doing so may cause issues
with updating the table/featureclass in the dictionary above or cause slow downs
*/
if( !IsEmpty( Example ) ){
	
	// Set the result to the main field for the attribute rule
    var EditInfo = { result : Example , edit : [] }
    
	// Loop through the list of table/feature names in the dictionary above
    for( var TableName in TableSets ){
		
		// The values dictionary is the default for populating the array of
		// edits depending on the type of edits that needes to be applied.
        var Values = { adds : [] , updates : [] , deletes : [] }
        
		// Get the values of the dictionary
        var TableInfo = TableSets[ TableName ]
			
		// Apply the filter to the feature/table if the query is not empty
        var Table = TableInfo.FS
		if( !IsEmpty( TableInfo.Query ) ){ Table = Filter( TableInfo.FS , TableInfo.Query ) }
		
		// Get the dictionary of values
        var ValueDict = TableInfo.DefaultValues
			
		// Get the row count of the table( optional )
        var TableCount = Count( Table )
        
		//If the name matches the specified table/feature name
        if( Tablename == TableOrFeature_Name ){
			// If the count is equal to 0 then add the record
            if( TableCount == 0 ){ PopulateEditsArray( Values.adds , Null , ValueDict ) }
			// If the count is equal to 1 then get the first record
            else if( TableCount == 1 ){
                Table = First( Table )
				// If there are changes in the attributes then update the table
                if( CheckDifferences( Table , ValueDict ) ){ PopulateEditsArray( Values.updates , Table[ OIDField ] , ValueDict ) }
                }
            }
		
		/*
		Set the edit dictionary to the function that is created above.
		If using an sde feature/table then set the 'schema owner' + 'char' + 'tablename'.
		If there is no character separator or schema/database owner then simply include
		the feature/table name.
		*/
		if( !IsEmpty( SchemaOwner ) || !IsEmpty( CharSep ) ){ TableName = SchemaOwner + CharSep + TableName }
        EditInfo = FeatureEdits( EditInfo , TableName , Values )
        }
	// Apply the edit to the featureclass/table if the edit array count is greater than 0
    if( Count( EditInfo.edit ) > 0 ){ return EditInfo }
    }

 

 

  1. Next you will want to create a separate table with a single field, ideally a date and time field, to be updated by the code above.
  2. Change the following in the code above

 

var TableSets = {}
TableSets[ TableOrFeature_Name ] = {
    'FS' : FeatureSetByName( $datastore, "<TableOrFeature_Name>", [ <'Array of Field Names'> ] ),
    'Query' : OIDField + ' = 1',
    'DefaultValues' : Dictionary( DateTimeField , Today() )// Modify to match the date field in the newly created table
    }

 

Note** You can modify the code to look for different conditions, but dates typically are easier to utilize.

After the table is created, do the following:

  1.  Create another attribute rule using the same code above to populate other feature classes/tables. Be sure to change the query conditions/checks/ and any other conditions in order to update the other features properly.
  2. Set the field to the date time field created to only trigger to look like the following

 

if( DateValue == Today() )// Line 97

 

  • Set the trigger fields to either insert and/or udpate
  • Check "Exclude from Application"

If done correctly, every time the conditions are met, the edits should apply to all features every time the table above is updated, or more profoundly, whenever this table is updated by any other feature.

4 Comments
Contributors
About the Author
I currently work as a Fire Data Analyst at Cobb County Fire Department.