Thursday, February 21, 2013

Query Feature Service By Object IDs (Python)

To query a feature service using object ids, you need to perform a POST.  For those who don't know the difference between a "GET" and "POST" here is a quick blurb based on the HTML specifications:
"POST" means that former means that form data is to be encoded (by a browser) into a URL while the "GET" means that the form data is to appear within a message body. 

Even simpler, "GET" is basically for just getting data where a "POST" may involve anything, like updating data, sending, or creating data.

Using python, you can perform both "GET" and "POST" methods, but since we need a "POST" to query by IDs, here is a simple example.  Please note that most feature services limit 1000 features being returned, so if you want to grab all of the features from a feature service, you'll have to perform multiple queries to get all the features back in JSON format.

Example:


import urllib2
import urllib
import urlparse
import httplib

def query_by_objectid(url, objectIDStart=0, objectIDEnd=1001):
    """ performs a POST operation where the query is called using
        the object id method.  If a feature service has more than
        1000 records, use this method to get a range of features
        from the feature service.

        Inputs:
           :url:  - string of feature service URL
           :objectIDStart: - integer of the start whole number
           :objectIDEnd: - end range whole number
        Returns:
           returns string JSON of query
    """
    url = url + '/query'
    start = int(objectIDStart)
    end = int(objectIDEnd)

    objectIDs = ",".join([str(x) for x in range(start, end)])
    headers = {"Content-type": "application/x-www-form-urlencoded",
               "Accept": "text/plain"}
    parameters = {'objectIds' : objectIDs,
                  'f' : 'json'}
    urlparams = urllib.urlencode(parameters)
    parts = urlparse.urlparse(url)
    h = httplib.HTTPConnection(parts.netloc)
    headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
    h.request('POST', parts.path, urlparams, headers)
    r = h.getresponse()
    return r.read()

if __name__ == "__main__":
    url = 'http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/TaxParcel/AssessorsLiveLayers/MapServer/1'
    print query_by_objectid(url=url,
                            objectIDStart=0,
                            objectIDEnd=5)

So we have a simple "POST" example. This sample should work with both ArcGIS Server 10.1 and ArcGIS Online feature services.

Please support my idea of having a python GUI by voting it up here.

Enjoy

3 comments:

sean.gillies said...

You've crossed up GET and POST in your blurb, and technically it's HTTP that's the authority. POST requests include a body, no semantics are defined for GET request bodies (they'll generally be ignored).

Andrew said...

thanks sean. I'll fix that up soon.

Cecil James said...

This is great thanks.
How would you modify this to query features based on a where statement?
for example:

where: Owner = 'Parks'