ArcGIS Content Operations Skill
Purpose
Search, create, read, update, delete, clone, and organize items in ArcGIS Online.
When to Use
- Finding items by owner, type, tag, or title
- Bulk updating item properties (metadata, sharing, folders)
- Cloning items within or across organizations
- Organizing content into folders
- Deleting stale content
- Generating content inventories
Prerequisites
- Authenticated GIS connection (see arcgis-authentication skill)
Core Operations
Search for Items
def search_items(gis, query, item_type=None, max_items=100):
"""
Search for items in the organization.
Common queries:
- owner:username
- title:keyword
- tags:disaster-response
- type:"Feature Layer"
- modified:[2024-01-01 TO 2024-12-31]
"""
search_query = query
if item_type:
search_query += f' AND type:"{item_type}"'
items = gis.content.search(
query=search_query,
max_items=max_items,
sort_field="modified",
sort_order="desc"
)
return items
# Examples
my_items = search_items(gis, "owner:dragon_redcross")
feature_layers = search_items(gis, "tags:keystone", item_type="Feature Layer")
recent_maps = search_items(gis, "owner:me AND modified:[2024-01-01 TO NOW]", item_type="Web Map")
Get Item by ID
def get_item(gis, item_id):
"""Retrieve a specific item by its ID."""
item = gis.content.get(item_id)
if item is None:
raise ValueError(f"Item not found: {item_id}")
return item
# Usage
item = get_item(gis, "a1b2c3d4e5f6g7h8")
print(f"{item.title} ({item.type}) - {item.numViews} views")
Update Item Properties
def update_item(item, properties):
"""
Update item properties.
Common properties:
- title, description, snippet, tags
- accessInformation, licenseInfo
- extent (as [[xmin,ymin],[xmax,ymax]])
"""
result = item.update(item_properties=properties)
if result:
print(f"Updated: {item.title}")
else:
print(f"Failed to update: {item.title}")
return result
# Usage
update_item(item, {
"description": "Updated via automation",
"tags": ["disaster-response", "2024", "automated"]
})
Bulk Update Pattern
def bulk_update_items(items, properties, dry_run=True):
"""Update multiple items with same properties."""
results = {"success": [], "failed": []}
for item in items:
if dry_run:
print(f"[DRY RUN] Would update: {item.title}")
results["success"].append(item.id)
else:
try:
item.update(item_properties=properties)
results["success"].append(item.id)
print(f"Updated: {item.title}")
except Exception as e:
results["failed"].append({"id": item.id, "error": str(e)})
print(f"Failed: {item.title} - {e}")
return results
Clone Item
def clone_item(gis, item, folder=None, title_suffix=" (Copy)"):
"""Clone an item within the same org."""
cloned = gis.content.clone_items(
items=[item],
folder=folder,
copy_data=True,
search_existing_items=False
)
if cloned:
new_item = cloned[0]
new_item.update(item_properties={"title": item.title + title_suffix})
return new_item
return None
Clone Across Organizations
def clone_to_org(source_gis, target_gis, item_id, target_folder=None):
"""Clone item from one org to another."""
source_item = source_gis.content.get(item_id)
cloned = target_gis.content.clone_items(
items=[source_item],
folder=target_folder,
copy_data=True
)
return cloned
Folder Management
def ensure_folder(gis, folder_name):
"""Create folder if it doesn't exist."""
folders = gis.users.me.folders
existing = [f["title"] for f in folders]
if folder_name not in existing:
gis.content.create_folder(folder_name)
print(f"Created folder: {folder_name}")
return folder_name
def move_to_folder(item, folder_name):
"""Move item to specified folder."""
item.move(folder_name)
print(f"Moved {item.title} to {folder_name}")
Delete Items
def delete_items(items, dry_run=True):
"""Delete items with dry-run safety."""
for item in items:
if dry_run:
print(f"[DRY RUN] Would delete: {item.title} ({item.id})")
else:
try:
item.delete()
print(f"Deleted: {item.title}")
except Exception as e:
print(f"Failed to delete {item.title}: {e}")
Generate Content Inventory
def generate_inventory(gis, owner=None):
"""Generate inventory of all items for an owner."""
query = f"owner:{owner}" if owner else "owner:me"
items = gis.content.search(query=query, max_items=1000)
inventory = []
for item in items:
inventory.append({
"id": item.id,
"title": item.title,
"type": item.type,
"created": item.created,
"modified": item.modified,
"views": item.numViews,
"size": item.size,
"tags": item.tags,
"folder": item.ownerFolder,
"shared": item.access
})
return inventory
Gotchas & Limitations
- Search max: Default search returns 10 items. Always specify max_items.
- Clone limitations: Some item types (Survey123, Workforce) have special clone requirements.
- Sharing inheritance: Cloned items don't inherit sharing settings - must set explicitly.
- Delete cascade: Deleting a Feature Layer Service deletes all dependent views.
Red Cross Specific Notes
- Use folders to separate projects:
Keystone/,RedGlide/,Shelters/ - Tag convention:
project-name,year,region,data-type - Always check dependencies before deleting (see arcgis-dependency-mapper skill)
Related Skills
- arcgis-authentication (required)
- arcgis-bulk-metadata (extends update operations)
- arcgis-dependency-mapper (check before delete)
