Append to hosted Feature layer from local gdb, Python

4369
7
Jump to solution
09-11-2020 02:35 PM
BenjaminMittler
Occasional Contributor III

Hi All, 

I spent pretty much all day today trying to figure out how to append date to a hosted feature layer from a feature class in a gdb. The documentation found from ESRI makes it seem that i first need to upload my gdb to ArcGIS Online in order to give it an ID, is this true. Is there no simple way to append data to a hosted feature service from a gdb feature layer if they both have the same schema?

1 Solution

Accepted Solutions
MehdiPira1
Esri Contributor

Hi Benjamin Mittler‌,

Here's the code you can use to append to a hosted feature layer from a gdb feature class.

You just need to change/update, add/delete the attributes based on your hosted feature layer and your gdb feature class attributes and change other variables too.

from arcgis import GIS
import pandas as pd
from arcgis.features import GeoAccessor, GeoSeriesAccessor
from arcgis import geometry
from copy import deepcopy

gis = GIS('url', 'username', 'password')

sdf_to_append = pd.DataFrame.spatial.from_featureclass(r"path to gdb feature class")

#search for the hosted feature layer/service
featureLayer_item = gis.content.search('type: "Feature Service" AND title:"xxxxx"')

#access the item's feature layers
feature_layers = featureLayer_item[0].layers

#query all the features
fset = feature_layers[0].query()

features_to_be_added = []
template_hostedFeature = deepcopy(fset.features[0])

for index, row in sdf_to_append.iterrows():
    x = sdf_to_append.loc[index]['SHAPE']['x']
    y = sdf_to_append.loc[index]['SHAPE']['y']
    new_feature = deepcopy(template_hostedFeature)
    input_geometry = {'y':float(y), 'x':float(x)}
    output_geometry = geometry.project(geometries = [input_geometry],
                                       in_sr = 3857, 
                                       out_sr = 3857,
                                       gis = gis)

    # assign the updated values
    new_feature.geometry = output_geometry[0]
    new_feature.attributes['HoleID'] = row['HoleID']
    new_feature.attributes['Project'] = row['Project']
    new_feature.attributes['InterFrom'] = row['InterFrom']
    new_feature.attributes['InterTo'] = row['InterTo']
    new_feature.attributes['Grade'] = row['Grade']
    new_feature.attributes['GramMetre'] = row['GramMetre']
    new_feature.attributes['RegoProf'] = row['RegoProf']
    new_feature.attributes['MidPoint'] = row['MidPoint']
    new_feature.attributes['IntercptNo'] = row['IntercptNo']
    new_feature.attributes['Overlap'] = row['Overlap']
    new_feature.attributes['EndDate'] = row['EndDate']
    new_feature.attributes['EAST'] = row['EAST']
    new_feature.attributes['NORTH'] = row['NORTH']
    new_feature.attributes['RL'] = row['RL']
    new_feature.attributes['Width'] = row['Width']  
    
    features_to_be_added.append(new_feature)

feature_layers[0].edit_features(adds = features_to_be_added) 
print("Hosted feature layer is updated with gdb feature class!")

‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I hope that's helpful.

View solution in original post

7 Replies
RandyBurton
MVP Alum

You should be able to use the ArcGIS REST API Add Features to accomplish the task.  The basic steps would be to use a SearchCursor to read the data from your geodatabase, construct a json object of the features to transfer, then use Add Features to add the items to your hosted feature.

You can also use the ArcGIS API for Python.  See Append Features for more information.  Also, the FeatureLayer.edit_features may be of interest.

0 Kudos
kjseitz2
New Contributor II

How do you get REST API to look at local gdb's though? I was going down this path until I couldn't figure out how to make REST target local layers vs the web layer I was on.

0 Kudos
MehdiPira1
Esri Contributor

Hi Benjamin Mittler‌,

Here's the code you can use to append to a hosted feature layer from a gdb feature class.

You just need to change/update, add/delete the attributes based on your hosted feature layer and your gdb feature class attributes and change other variables too.

from arcgis import GIS
import pandas as pd
from arcgis.features import GeoAccessor, GeoSeriesAccessor
from arcgis import geometry
from copy import deepcopy

gis = GIS('url', 'username', 'password')

sdf_to_append = pd.DataFrame.spatial.from_featureclass(r"path to gdb feature class")

#search for the hosted feature layer/service
featureLayer_item = gis.content.search('type: "Feature Service" AND title:"xxxxx"')

#access the item's feature layers
feature_layers = featureLayer_item[0].layers

#query all the features
fset = feature_layers[0].query()

features_to_be_added = []
template_hostedFeature = deepcopy(fset.features[0])

for index, row in sdf_to_append.iterrows():
    x = sdf_to_append.loc[index]['SHAPE']['x']
    y = sdf_to_append.loc[index]['SHAPE']['y']
    new_feature = deepcopy(template_hostedFeature)
    input_geometry = {'y':float(y), 'x':float(x)}
    output_geometry = geometry.project(geometries = [input_geometry],
                                       in_sr = 3857, 
                                       out_sr = 3857,
                                       gis = gis)

    # assign the updated values
    new_feature.geometry = output_geometry[0]
    new_feature.attributes['HoleID'] = row['HoleID']
    new_feature.attributes['Project'] = row['Project']
    new_feature.attributes['InterFrom'] = row['InterFrom']
    new_feature.attributes['InterTo'] = row['InterTo']
    new_feature.attributes['Grade'] = row['Grade']
    new_feature.attributes['GramMetre'] = row['GramMetre']
    new_feature.attributes['RegoProf'] = row['RegoProf']
    new_feature.attributes['MidPoint'] = row['MidPoint']
    new_feature.attributes['IntercptNo'] = row['IntercptNo']
    new_feature.attributes['Overlap'] = row['Overlap']
    new_feature.attributes['EndDate'] = row['EndDate']
    new_feature.attributes['EAST'] = row['EAST']
    new_feature.attributes['NORTH'] = row['NORTH']
    new_feature.attributes['RL'] = row['RL']
    new_feature.attributes['Width'] = row['Width']  
    
    features_to_be_added.append(new_feature)

feature_layers[0].edit_features(adds = features_to_be_added) 
print("Hosted feature layer is updated with gdb feature class!")

‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I hope that's helpful.

MehdiPira1
Esri Contributor

Hi Benjamin Mittler‌,

Please mark as helpful if you find it helpful. If it answered your question please mark it as answered.

Thank you.

0 Kudos
BenjaminMittler
Occasional Contributor III

Hi Mehdi, 

Thank you for the reply. I will mark your response as correct. However, it was significantly easier to append data to a local copy of the data and then use that layer to completely overwrite the hosted feature layer daily. This was the method I went. 

Best, 

Ben

DarrylKlassen1
Occasional Contributor II

Can you post the code you used to do this "easier" method?  Thanks

0 Kudos
TaylorCarnell1
New Contributor III

If your local data matches the feature layer exactly and you don't need to reconcile schema differences etc. then it is easier to do:

 

sdf_to_append = pd.DataFrame.spatial.from_featureclass(r"path to gdb feature class")
feat_set = FeatureSet.from_dataframe(sdf_to_append)
feature_layers[0].edit_features(adds = feat_set)