Select to view content in your preferred language

update.da.cursor question about fields

46
1
yesterday
CW-GIS
by
Regular Contributor

Hi everyone,

I'm stuck on a situation that I feel I'm making more complicated than it needs to be.

Situation: 

I have a database (700K records) that updates daily, I convert it to a spatial dataframe. I have a hosted feature layer (points) that updates daily. Right now I truncate and append the entire thing, but having it empty for a while isn't ideal.

I want to basically this:

  • For each row in the database, search for the same 'key' in the hosted.
  • If return clause = 1
  • If any of the fields have different values, then update that field (or just the entire row)
  • else 
  • If return clause = 0
  • insert cursor to insert that row
  • else next row

Where I am getting confused is, does the da.cursor just use field position to insert values? row[19] will update the 19th column. But what if someone inserts a new column in the database, would everything get screwed up? Can I instead just match the field names with a field map?

0 Kudos
1 Reply
DanPatterson
MVP Esteemed Contributor

Fields are always added to the end.

If you want to get the field names prior to processing you can, and then produce an index to the name.

A simple example

 

fc0 = r'C:\\arcpro_npg\\Project_npg\\tests.gdb\\sq2'
from arcpy.da import SearchCursor
with SearchCursor(fc0, "*") as cursor:
    fld_names = cursor.fields
    n = len(fld_names)
    rpt = list(zip(range(0, n), fld_names))
    print(f"{rpt}")
    for row in cursor:
        print(f'{row[0]}')
        
[(0, 'OBJECTID'), (1, 'Shape'), (2, 'ids'), (3, 'CENTROID_X'),
 (4, 'CENTROID_Y'), (5, 'INSIDE_X'), (6, 'INSIDE_Y'),
 (7, 'PART_COUNT'), (8, 'PNT_COUNT'), (9, 'Sort_'),
 (10, 'Shape_Length'), (11, 'Shape_Area'), (12, 'Text')
, (13, 'Long_'), (14, 'Float_')]
1
2
3
4
5
6
9

 

There is limited information that you can get from the cursor

 

dir(cursor)
['__class__', '__delattr__', '__dir__', '__doc__', '__enter__', '__eq__',
 '__esri_toolinfo__', '__exit__', '__format__', '__ge__', '__getattribute__',
 '__getitem__', '__getstate__', '__gt__', '__hash__', '__init__',
 '__init_subclass__', '__iter__', '__le__', '__lt__', '__ne__', '__new__',
 '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
 '__sizeof__', '__str__', '__subclasshook__',
 '_as_narray', '_dtype',
 'fields', 'next', 'reset']

# -- example
cursor._dtype
dtype([('OBJECTID', '<i4'), ('Shape', '<f8', (2,)), ('ids', '<i4'),
       ('CENTROID_X', '<f8'), ('CENTROID_Y', '<f8'), ('INSIDE_X', '<f8'),
       ('INSIDE_Y', '<f8'), ('PART_COUNT', '<f8'), ('PNT_COUNT', '<f8'),
       ('Sort_', '<i4'), ('Shape_Length', '<f8'), ('Shape_Area', '<f8'),
       ('Text', '<U20'), ('Long_', '<i4'), ('Float_', '<i4')])

 

the _as_narray can't be used if the fields includes the geometry, in such cases, you can use arcpy's FeatureClassToNumPyArray or TableToNumPyArray


... sort of retired...
0 Kudos