Liking cljdoc? Tell your friends :D

geo

Multi-provider geocoding abstraction with automatic fallback chain, DB-backed caching, per-provider rate limiting, and Haversine distance calculation.

Key namespaces

NamespaceLayerResponsibility

boundary.geo.schema

shared

Malli schemas: GeoPoint, AddressQuery, GeoResult, GeoConfig

boundary.geo.ports

shared

GeoProviderProtocol, GeoCacheProtocol

boundary.geo.core.math

core

haversine-distance, bearing

boundary.geo.core.address

core

normalize-query, query-hash (SHA-256)

boundary.geo.shell.adapters.osm

shell

Nominatim adapter (no API key required)

boundary.geo.shell.adapters.google

shell

Google Maps adapter (requires BND_GEO_API_KEY)

boundary.geo.shell.adapters.mapbox

shell

Mapbox adapter (requires BND_GEO_API_KEY)

boundary.geo.shell.cache

shell

DbGeoCache — next.jdbc-backed, geo_cache table

boundary.geo.shell.service

shell

Public API: geocode!, reverse-geocode!, distance

Configuration

;; OpenStreetMap only (no API key)
:boundary/geo-service
{:provider   :openstreetmap
 :user-agent "MyApp/1.0 (contact@example.com)"
 :cache-ttl  86400   ; 24 hours
 :db         #ig/ref :boundary/db}

;; Fallback chain: OSM first, then Google
:boundary/geo-service
{:provider   :openstreetmap
 :fallback   {:provider :google :api-key #env BND_GEO_API_KEY}
 :user-agent "MyApp/1.0"
 :cache-ttl  86400
 :db         #ig/ref :boundary/db}

Usage

(require '[boundary.geo.shell.service :as geo])

;; Geocode an address
(geo/geocode! service {:address "Prinsengracht 263, Amsterdam"})
;=> {:lat 52.3747 :lon 4.8844 :formatted-address "Prinsengracht 263, Amsterdam"}

;; Reverse geocode
(geo/reverse-geocode! service {:lat 52.3747 :lon 4.8844})
;=> {:formatted-address "Prinsengracht 263, 1016 GV Amsterdam"}

;; Haversine distance (pure, no HTTP)
(geo/distance {:lat 52.3747 :lon 4.8844} {:lat 52.3702 :lon 4.8952})
;=> 0.84  ; kilometres

Rate limiting

  • OpenStreetMap (Nominatim): 1 request/second enforced

  • Google / Mapbox: 100 ms between requests

  • Do not share an adapter instance across threads

DB migration

Apply the geo_cache table migration before first use:

clojure -M:migrate up

Migration file: resources/boundary/geo/migrations/001-geo-cache.sql

Testing

clojure -M:test:db/h2 :geo

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close