Select to view content in your preferred language

Rebuild Spatial Index for Hosted Feature layers

507
2
Jump to solution
01-27-2026 09:19 AM
MariusVerdes
Frequent Contributor

Hello everyone,

We are running ArcGIS Enterprise 11.5 and I am looking to automate the process of rebuilding spatial indexes for hosted feature layers.

I am aware that this can be done manually through the Portal UI by going to the hosted feature layer item → Settings → Feature Layer (Hosted) → Indexes, where the spatial index can be rebuilt. Since this functionality exists and is supported in the Portal interface, I assume it is calling some internal operation.

However, I have not been able to find any documented or supported way to trigger the same spatial index rebuild programmatically using the REST API, ArcGIS API for Python, or a geoprocessing tool. I did come across the following community post, but it is unclear whether it applies only to ArcGIS Online or if it is relevant to ArcGIS Enterprise as well:
https://community.esri.com/t5/arcgis-online-questions/automate-task-to-rebuild-spatial-index-of-host...

Has anyone identified a supported method to automate the same spatial index rebuild that is available in the Portal UI for hosted feature layers in ArcGIS Enterprise? Or is this currently only possible through manual interaction in the Portal?

Any insights or confirmation would be greatly appreciated. Thank you.

0 Kudos
1 Solution

Accepted Solutions
ZenMasterZeke
Frequent Contributor

from arcgis.gis import GIS
from arcgis.features import FeatureLayerCollection

 

# 1) Sign in (use a user with admin or owner privileges)
gis = GIS("https://your-portal-url/portal", "admin_user", "admin_password")

 

# 2) Get the Feature Layer item (hosted)
item = gis.content.get("ITEM_ID_OF_HOSTED_FEATURE_LAYER")
flc = FeatureLayerCollection.fromitem(item)

 

# 3) Loop sublayers, find spatial index name, and rebuild it
for lyr in flc.layers:  # each is a FeatureLayer
    idxs = getattr(lyr.properties, "indexes", [])
    # find spatial index for this sublayer
    shape_idx = next((i for i in idxs if i.get("fields") == "Shape"), None)
    if not shape_idx:
        print(f"No spatial index found for layer {lyr.properties.name}; skipping.")
        continue

 

    payload = {"indexes": [{"name": shape_idx["name"], "fields": "Shape"}]}
    # 4) Call updateDefinition on the Admin endpoint via the Python API wrapper
    result = lyr.manager.update_definition(payload)  # returns {"success": true} on success
    print(lyr.properties.name, result)

View solution in original post

2 Replies
ZenMasterZeke
Frequent Contributor

from arcgis.gis import GIS
from arcgis.features import FeatureLayerCollection

 

# 1) Sign in (use a user with admin or owner privileges)
gis = GIS("https://your-portal-url/portal", "admin_user", "admin_password")

 

# 2) Get the Feature Layer item (hosted)
item = gis.content.get("ITEM_ID_OF_HOSTED_FEATURE_LAYER")
flc = FeatureLayerCollection.fromitem(item)

 

# 3) Loop sublayers, find spatial index name, and rebuild it
for lyr in flc.layers:  # each is a FeatureLayer
    idxs = getattr(lyr.properties, "indexes", [])
    # find spatial index for this sublayer
    shape_idx = next((i for i in idxs if i.get("fields") == "Shape"), None)
    if not shape_idx:
        print(f"No spatial index found for layer {lyr.properties.name}; skipping.")
        continue

 

    payload = {"indexes": [{"name": shape_idx["name"], "fields": "Shape"}]}
    # 4) Call updateDefinition on the Admin endpoint via the Python API wrapper
    result = lyr.manager.update_definition(payload)  # returns {"success": true} on success
    print(lyr.properties.name, result)
MariusVerdes
Frequent Contributor

Hello @ZenMasterZeke ,
Thanks a lot for the example, it helped a lot.

What I managed to do is to convert it to check for all hosted services in the Enterprise Portal and rebuild the spatial index for those with Sync disabled, please see it below:

"from arcgis.gis import GIS
from arcgis.features import FeatureLayerCollection
import datetime

# Configuration
PORTAL_URL = "https://your-portal-url/portal"
USERNAME = "admin_user"
PASSWORD = "admin_password"

print(f"Connecting to {PORTAL_URL}...")
gis = GIS(PORTAL_URL, USERNAME, PASSWORD, verify_cert=False)
print(f"Connected as: {gis.properties.user.username}\n")

# Search for hosted feature services (excluding views)
print("Searching for hosted feature services...")
items = gis.content.search(
query="type:'Feature Service' AND typekeywords:Hosted AND -typekeywords:'View Service'",
max_items=1000,
outside_org=False
)

print(f"Found {len(items)} hosted feature services\n")
print("="*80)

# Tracking
services_checked = 0
layers_rebuilt = 0
services_skipped_sync = 0
layers_skipped_no_index = 0
layers_failed = []

for item in items:
services_checked += 1
print(f"\n[{services_checked}/{len(items)}] {item.title} (Owner: {item.owner})")

try:
flc = FeatureLayerCollection.fromitem(item)

# Check sync
if flc.properties.get('syncEnabled') or 'Sync' in flc.properties.get('capabilities', ''):
print(" SKIPPED: Sync enabled")
services_skipped_sync += 1
continue

# Process each spatial layer
for lyr in flc.layers:
layer_name = lyr.properties.get('name', 'Unknown')
print(f" └─ Layer: {layer_name}")

# Get indexes from layer properties
indexes = lyr.properties.get("indexes", [])

# Find the spatial index - case-insensitive check for "shape"
spatial_idx = next((idx for idx in indexes if idx.get("fields", "").lower() == "shape"), None)

if not spatial_idx:
print(f" ⚠ No spatial index found, skipping")
layers_skipped_no_index += 1
continue

# Rebuild by passing existing index definition back
try:
payload = {"indexes": [{"name": spatial_idx["name"], "fields": spatial_idx["fields"]}]}
result = lyr.manager.update_definition(payload)

if result.get('success'):
print(f" ✓ Spatial index '{spatial_idx['name']}' rebuilt successfully")
layers_rebuilt += 1
else:
print(f" ✗ FAILED: {result}")
layers_failed.append(f"{item.title}/{layer_name}: {result}")

except Exception as e:
print(f" ✗ EXCEPTION: {e}")
layers_failed.append(f"{item.title}/{layer_name}: {e}")

except Exception as e:
print(f" ! ERROR: {e}")
layers_failed.append(f"{item.title}: {e}")

# Summary
print("\n" + "="*80)
print("SUMMARY")
print("="*80)
print(f"Services checked: {services_checked}")
print(f"Layers rebuilt: {layers_rebuilt}")
print(f"Services skipped (sync): {services_skipped_sync}")
print(f"Layers skipped (no index): {layers_skipped_no_index}")
print(f"Failed: {len(layers_failed)}")

if layers_failed:
print("\nFailed operations:")
for failed in layers_failed:
print(f" - {failed}")

print(f"\nCompleted: {datetime.datetime.now()}")"

0 Kudos