Apologies for a solution using a different set of technologies, but this is something that is very well suited for SQL. A series of self-joins can be used to find nearest neighbors. Example below is using PostgreSQL and PostGIS using New Jersey municipality data.
WITH camden AS (
SELECT shape
FROM municipalities
WHERE mun = 'CAMDEN CITY'
)
SELECT mun AS Neighbors
FROM municipalities
JOIN camden ON ST_Touches(camden.shape, municipalities.shape)
;
Produces:
"WOODLYNNE BORO"
"COLLINGSWOOD BORO"
"HADDON TWP"
"GLOUCESTER CITY"
"OAKLYN BORO"
"PENNSAUKEN TWP"
I selected just Camden City using a CTE expression ("with" statement) and then joined that to the municipalities table using a spatial function as the join predicate. ST_Touches returns TRUE if the features touch.
This can be expanded out to all municipalities, using a self join.
SELECT a.mun AS Municipality
, b.mun AS Neighbors
FROM municipalities a
JOIN municipalities b ON ST_Touches(a.shape, b.shape)
;
Produces the following (sampled two municipalities' results):
"HAMMONTON TOWN"; "HAMILTON TWP"
"HAMMONTON TOWN"; "MULLICA TWP"
"HAMMONTON TOWN"; "WASHINGTON TWP"
"HAMMONTON TOWN"; "SHAMONG TWP"
"HAMMONTON TOWN"; "FOLSOM BORO"
"HAMMONTON TOWN"; "WINSLOW TWP"
"HAMMONTON TOWN"; "WATERFORD TWP"
"RANDOLPH TWP"; "MINE HILL TWP"
"RANDOLPH TWP"; "PARSIPPANY-TROY HILLS TWP"
"RANDOLPH TWP"; "DOVER TOWN"
"RANDOLPH TWP"; "DENVILLE TWP"
"RANDOLPH TWP"; "ROXBURY TWP"
"RANDOLPH TWP"; "ROCKAWAY TWP"
"RANDOLPH TWP"; "CHESTER TWP"
"RANDOLPH TWP"; "MENDHAM TWP"
"RANDOLPH TWP"; "MORRIS TWP"
"RANDOLPH TWP"; "VICTORY GARDENS BORO"
You can go even more once you're working in SQL. Go the further step and calculate directions (Northwest, Southeast, etc) using ST_Azimuth:
SELECT a.mun AS Municipality
, b.mun AS Neighbors
, ST_Azimuth( ST_Centroid(a.shape)
, ST_Centroid(b.shape) ) / (2*pi())*360 AS direction
FROM municipalities a
JOIN municipalities b ON ST_Touches(a.shape, b.shape)
;
Adds the "direction" column:
"CAMDEN CITY"; "COLLINGSWOOD BORO"; 129.847424758369
"CAMDEN CITY"; "OAKLYN BORO"; 149.434213414794
"CAMDEN CITY"; "GLOUCESTER CITY"; 190.159321103297
"CAMDEN CITY"; "PENNSAUKEN TWP"; 54.1779392174728
"CAMDEN CITY"; "HADDON TWP"; 131.032906760376
Here's a presentation I gave that talks about moving away from Desktop GIS and relying more on what your spatial database can do for you.
Hope this helps!
Update: here is using a Recursive CTE to determine neighboring polygons. I am again using NJ municipality data, clipped down to just Camden County, using Camden City as the starting point.
CREATE TABLE public.camden_neighbor AS
WITH RECURSIVE neighbors (mun_code, shape, depth, path, cycle) AS (
SELECT m.mun_code, m.shape, 0
, array[m.mun_code::text], false
FROM municipalities m
WHERE m.mun = 'CAMDEN CITY'
UNION ALL
SELECT DISTINCT m.mun_code, m.shape, nm.depth+1
, path || m.mun_code::text
, m.mun_code = ANY(path)
FROM municipalities m, neighbors nm
WHERE ST_Touches(m.shape, nm.shape)
AND NOT m.mun_code = ANY(path)
AND nm.depth < 5
)
SELECT DISTINCT mun_code, MIN(depth) as depth
from neighbors
group by mun_code
ORDER BY 2, 1
;
Cribbed from the PostgreSQL documentation on Recursive CTEs, I use a depth, path, and cycle column to determine the Order and if the currently evaluated record has been seen before. From there, the results are stuffed into a new, non-spatial table. I then linked the table up to the spatial data in GIS using the "mun_code" field as a key.