Create Locator; Using Services as the Data Source

1151
4
11-25-2020 08:59 AM
JoeBorgione
MVP Emeritus

ArcGIS Pro 2.6

Yesterday I successfully created a multi-role locator using the Create Locator tool. Three of the four data sources are rest-end services.

I would like to automate the task in a python script and things aren't quite working for me and I'm not sure why. The history of the tool is my source for the parameters.  I've used it before but the data sources were feature classes rather than services.  At any rate, here is what I use and the ensuing error:

 

countryCode = 'USA'
addressPrimary = r'https://path/to/rest/services/Reference/MapServer/5'
centerlinesPrimary = r'https://path/to/rest/services/Transportation/MapServer/0'
parcelsPrimary = r'https://path/tos/rest/services/Land/MapServer/1'
poiPrimary = r'\\SDE\Connection\To\Our.sde\owner.AddressGridCoordinatePoints'

#primaryReferenceData = "{} PointAddress;{} StreetAddress;{} POI".format(addressPrimary,centerlinesPrimary,
                          #parcelsPrimary)

primaryReferenceData = f'{addressPrimary} PointAddress;{centerlinesPrimary} StreetAddress;{parcelsPrimary} Parcel;{poiPrimary} POI'

outLocator =  r'M:\HansenSQL\HansenGeocodingTestMultiRole'

fieldMapping = "'PointAddress.HOUSE_NUMBER 5.ADDR_HN';"\
                "'PointAddress.STREET_PREFIX_DIR 5.ADDR_PD';"\
                "'PointAddress.STREET_NAME 5.ADDR_SN';"\
                "'PointAddress.STREET_SUFFIX_TYPE 5.ADDR_ST';"\
                "'PointAddress.STREET_SUFFIX_DIR 5.ADDR_SD';"\
                "'PointAddress.SUB_ADDRESS_UNIT 5.UNIT_DESIG';"\
                "'PointAddress.CITY 5.CITY';"\
                "'StreetAddress.HOUSE_NUMBER_FROM_LEFT 0.FROMADDR_L';"\
                "'StreetAddress.HOUSE_NUMBER_TO_LEFT 0.TOADDR_L';"\
                "'StreetAddress.HOUSE_NUMBER_FROM_RIGHT 0.FROMADDR_R';"\
                "'StreetAddress.HOUSE_NUMBER_TO_RIGHT 0.TOADDR_R';"\
                "'StreetAddress.STREET_PREFIX_DIR 0.PREDIR';"\
                "'StreetAddress.STREET_NAME 0.NAME';"\
                "'StreetAddress.STREET_SUFFIX_TYPE 0.POSTTYPE';"\
                "'StreetAddress.STREET_SUFFIX_DIR 0.POSTDIR';"\
                "'Parcel.PARCEL_NAME 1.parcel_id';"\
                "POI.PLACE_NAME 'owner.AddressGridCoordinatePoints'.Coordinates"

Error:

Failed to execute. Parameters are not valid.
ERROR 002782: Selected Primary Table does not contain geometry.

I don't care for this new code editor as it doesn't list line numbers, but I'll limp through this.

Notice in the field mapping portion it refers to the feature id only; does it need to be fully qualified with the entire url?

@ShanaBritt 

@BradNiemand 

That should just about do it....
4 Replies
JoeBorgione
MVP Emeritus

The help page has a sample; I'll see what I need to do to get it to work for me...

That should just about do it....
0 Kudos
JoeBorgione
MVP Emeritus

Following the example towards the bottom of the help page mentioned, I am trying to create a single role street address locator with a service as the data source: (sorry for the lame code editing, but I'm at the mercy of the new geonet)

import arcpy

arcpy.env.overwriteOutput = True
arcpy.SetLogHistory(False)


outLocator = r'M:\HansenSQL\HansenGeocoding\TestLocator'
language = 'ENG'
country = 'USA'


inTable = "https://blah/blahlah/rest/services/Transportation/MapServer/0 StreetAddress"

fieldMapping = "'StreetAddress.HOUSE_NUMBER_FROM_LEFT 0.FROMADDR_L';"\
"'StreetAddress.HOUSE_NUMBER_TO_LEFT 0.TOADDR_L';"\
"'StreetAddress.HOUSE_NUMBER_FROM_RIGHT 0.FROMADDR_R';"\
"'StreetAddress.HOUSE_NUMBER_TO_RIGHT 0.TOADDR_R';"\
"'StreetAddress.STREET_PREFIX_DIR 0.PREDIR';"\
"'StreetAddress.STREET_NAME 0.NAME';"\
"'StreetAddress.STREET_SUFFIX_TYPE 0.POSTTYPE';"\
"'StreetAddress.STREET_SUFFIX_DIR 0.POSTDIR'"

arcpy.geocoding.CreateLocator(country, inTable, fieldMapping, outLocator, language)

However, it errors out with:

ExecuteError: Failed to execute. Parameters are not valid.
ERROR 002782: Selected Primary Table does not contain geometry.
Failed to execute (CreateLocator).

I can think of two things:

I can get to the service via the create locator tool, but perhaps there is a security setting that does not allow me to hit it with python; I don't think that's it because in a console window I can use arcpy.ListFields(inTable) and get a list.

or

Creating a locator with a service as the data source simply does not work in python....

 

That should just about do it....
0 Kudos
BradNiemand
Esri Regular Contributor

Joe,

You need to call

arcpy.SignInToPortal(“https://machinename.domainname.com/portal”, “username”, “password”)

and then using services as data sources should work just fine for CreateLocator using Python. The data sources need to be on the server federated with the Portal you are signing into.

 

If your data sources are shared with everyone (public) you don’t need to call SignInToPortal() first.

 

Brad

JoeBorgione
MVP Emeritus

Turns out the arcpy.SignInToPotal() call isn't needed for me.  The game changer is while the create locator tool is able to exploit a map service as a data source, arcpy cannot; arcpy wants a feature service.

The portal I have access to is behind a firewall and is available 'publicly' to those users logged into the network which I am.  All I had to do is change the urls to the various feature services and I'm good to go.

One of the data sources in my multi-role locator is on our SDE-Egdb, so it's part of inTable variable as shown below in the final code:

 

 

import arcpy
arcpy.env.overwriteOutput = True
arcpy.SetLogHistory(False)

outLocator = r'M:\path_to\my_locator'
language = 'ENG'
country = 'USA'

inTable = "https://www.yady_yady.org/gisfed/rest/services/Internal/FeatureServer/1 PointAddress;"\
          "https://www.yady_yady.org/gisfed/rest/services/Internal/FeatureServer/9 StreetAddress;"\
          "https://www.yady_yady.org/gisfed/rest/services/Internal/FeatureServer/3 Parcel;"\
          "\\\sharedDrive\to\connectionFile.sde\OurSde.AddressGridCoordinatePoints POI"
          
fieldMapping = "'PointAddress.HOUSE_NUMBER 1.ADDR_HN';"\
                "'PointAddress.STREET_PREFIX_DIR 1.ADDR_PD';"\
                "'PointAddress.STREET_NAME 1.ADDR_SN';"\
                "'PointAddress.STREET_SUFFIX_TYPE 1.ADDR_ST';"\
                "'PointAddress.STREET_SUFFIX_DIR 1.ADDR_SD';"\
                "'PointAddress.SUB_ADDRESS_UNIT 1.UNIT_DESIG';"\
                "'PointAddress.CITY 1.CITY';"\
                "'StreetAddress.HOUSE_NUMBER_FROM_LEFT 9.FROMADDR_L';"\
                "'StreetAddress.HOUSE_NUMBER_TO_LEFT 9.TOADDR_L';"\
                "'StreetAddress.HOUSE_NUMBER_FROM_RIGHT 9.FROMADDR_R';"\
                "'StreetAddress.HOUSE_NUMBER_TO_RIGHT 9.TOADDR_R';"\
                "'StreetAddress.STREET_PREFIX_DIR 9.PREDIR';"\
                "'StreetAddress.STREET_NAME 9.NAME';"\
                "'StreetAddress.STREET_SUFFIX_TYPE 9.POSTTYPE';"\
                "'StreetAddress.STREET_SUFFIX_DIR 9.POSTDIR';"\
                "'Parcel.PARCEL_NAME 3.parcel_id';"\
                "POI.PLACE_NAME 'OurSde.AddressGridCoordinatePoints'.Coordinates"
                
arcpy.geocoding.CreateLocator(country, inTable, fieldMapping, outLocator, language)                

 

 

That should just about do it....
0 Kudos