How to query Feature Layer to get objects that have an attachment?

2659
2
Jump to solution
01-28-2022 04:15 AM
Manu
by
Occasional Contributor

I want to download attachments from an ArcGIS Online Feature Layer and use them for further operations. So far, I did this using

search_result = gis.content.search(ArcGIS_content, "Feature Layer")
item = search_result[0]
FeatureLayer = item.layers[0]
FeatureObjectIDs = FeatureLayer.query(where = "1=1", return_ids_only = True)

for objID in FeatureObjectIDs["objectIds"]:
    print("Checking object", str(objID) + "...")
    attachments_list = FeatureLayer.attachments.get_list(oid = objID)

in order to get the object IDs and then iterate through all items of the Feature Layer. However, this takes a lot of time and few items actually have an attachment. How can I change the where parameter so I get only the object IDs of objects with an attachment?

0 Kudos
1 Solution

Accepted Solutions
jcarlson
MVP Esteemed Contributor

The Attachment Manager submodule of the Python API does allow you to do a query on all attachments. If you do not specify a query string, it will return information about every attachment from the layer.

jcarlson_0-1643376625210.png

 

Notably, the output includes the parent object/global ID. You can pull that column out and turn around to query the parent service with that list.

l = gis.content.get('647e966722f943d0b5d49f82288a839e').layers[0] # adjust as needed to get your particular service / layer

attachments = l.attachments.search(as_df=True)

attachments['PARENTOBJECTID'].drop_duplicates().to_list()

The result: a list of objectids with attachments!

jcarlson_1-1643377563352.png

Now, that addresses the title of your post. But in the body of your post, you mention downloading the items, too. You could feed that objectid list into your original script if you like, but it's worth noting that using the attachments.search() method and returning the results as a dict (as opposed to a DataFrame), each attachment includes the property "DOWNLOAD_URL".

So you could try something like this:

downloads = [a['DOWNLOAD_URL'] for a in l.attachments.search()]

And then you have list of URLs from which you can iteratively download every attachment.

jcarlson_2-1643378003856.png

 

- Josh Carlson
Kendall County GIS

View solution in original post

2 Replies
JavierCMartínezPrieto
Occasional Contributor

hello
this code might help you, it is used in the arcgisonline notebook.

https://github.com/Esri/Survey123-tools/blob/4ad217209681f29c3ad98636e664a532c0ffd85a/Export_survey_...

Regards

Javier C. Martinez Prieto
0 Kudos
jcarlson
MVP Esteemed Contributor

The Attachment Manager submodule of the Python API does allow you to do a query on all attachments. If you do not specify a query string, it will return information about every attachment from the layer.

jcarlson_0-1643376625210.png

 

Notably, the output includes the parent object/global ID. You can pull that column out and turn around to query the parent service with that list.

l = gis.content.get('647e966722f943d0b5d49f82288a839e').layers[0] # adjust as needed to get your particular service / layer

attachments = l.attachments.search(as_df=True)

attachments['PARENTOBJECTID'].drop_duplicates().to_list()

The result: a list of objectids with attachments!

jcarlson_1-1643377563352.png

Now, that addresses the title of your post. But in the body of your post, you mention downloading the items, too. You could feed that objectid list into your original script if you like, but it's worth noting that using the attachments.search() method and returning the results as a dict (as opposed to a DataFrame), each attachment includes the property "DOWNLOAD_URL".

So you could try something like this:

downloads = [a['DOWNLOAD_URL'] for a in l.attachments.search()]

And then you have list of URLs from which you can iteratively download every attachment.

jcarlson_2-1643378003856.png

 

- Josh Carlson
Kendall County GIS