geolite 0.0.17

open source geocode solution
geolite-0.0.17 is not a library.

geolite

making openstreetmap data usable by anyone: from .osm.pbf to the first query answer.

open source geocode

actions quality coverage crates downloads


getting started

with cargo

$ cargo install geolite
$ geolite --version
$ geolite build brazil # needs +/- 45gb while building then +/- 3gb when finished
$ geolite http-server # open http://localhost:8080

with docker

# command line
$ docker run pjpimentel/geolite:latest --version
# pre-built geocoder of a continent
$ docker run -p 8080:8080 pjpimentel/geolite:prebuilt-south-america
# open http://localhost:8080

docs

  1. source code modules
    1. database
    2. osm-pbf-file
    3. osm-tag
    4. osm-node
    5. osm-way
    6. osm-relation
    7. admin-level
    8. admin-level-hierarchy
    9. house-number
    10. address
    11. cli
    12. http
  2. docker images
    1. base image
    2. pre-built images
  3. cookbook
    1. execute all necessary steps
    2. extract each data from a pbf file
    3. index extracted data
    4. optimize data
    5. query
    6. explore
    7. run the end-to-end suite

docker images

base image

$ docker run pjpimentel/geolite:latest --version
$ docker run -t -v ./geolite-data:/.geolite pjpimentel/geolite:latest build brazil

pre-built images

size matters: once a region's data grows too large for a docker image, its pre-built image stops being updated and may be dropped.

docker run -p 8080:8080 pjpimentel/geolite:prebuilt-south-america
docker run -p 8080:8080 pjpimentel/geolite:prebuilt-south-america-YYYYMMDDHHMM
# open http://localhost:8080

available images

the images are rebuilt on the 1st and the 15th of every month from the latest geofabrik extracts; the dated tag keeps each build.

# region docker cmd
1 south-america, one base per country, thirteen in all docker run -p 8080:8080 pjpimentel/geolite:prebuilt-south-america
2 portugal docker run -p 8080:8080 pjpimentel/geolite:prebuilt-portugal
3 netherlands docker run -p 8080:8080 pjpimentel/geolite:prebuilt-netherlands
4 switzerland docker run -p 8080:8080 pjpimentel/geolite:prebuilt-switzerland

cookbook

execute all necessary steps

$ geolite build brazil          # br/data.sqlite3 and br/index.tantivy, sealed
$ geolite build south-america   # one base per country, thirteen in all
# or with docker
$ docker run --rm -t -v ./geolite-data:/.geolite pjpimentel/geolite:latest build brazil
$ docker run --rm -p 8080:8080 -v ./geolite-data:/.geolite pjpimentel/geolite:latest http-server

extract each data from a pbf file

$ geolite osm-pbf-file download brazil
$ geolite exec extract-osm-pbf-blob-chunks brazil
$ geolite exec extract-osm-pbf-header brazil
$ geolite exec extract-osm-pbf-data brazil
# the two extraction stages read everything the osm data holds, every pbf decoded so far
$ geolite exec extract-osm-admin-levels
$ geolite exec extract-osm-house-numbers

index extracted data

# every base of the data path, or the ones named: `geolite exec index-addresses br`
$ geolite exec index-admin-levels-hierarchy
$ geolite exec index-addresses
$ geolite exec index-coordinates

optimize data

# deletes a country without children and a street without parents, then folds the ways of one
# street into one row: both read the hierarchy and clear the addresses and coordinates indexes,
# which have to be built again after them
$ geolite exec optimize-delete-isolated-admin-levels
$ geolite exec optimize-merge-admin-levels
$ geolite exec optimize-delete-intermediary-data
$ geolite exec optimize-sqlite-file

geolite exec runs one stage per call and refuses a stage whose requirements did not run, naming the one to run first; geolite exec --help lists the stages in the order the pipeline runs. a stage that reads a pbf names it (extract-osm-pbf-data brazil); the two extraction stages read everything the osm data holds; a stage that works on the bases runs over every base of the data path, or over the countries named (index-addresses br ar). geolite build runs optimize-delete-isolated-admin-levels, which removes a base it leaves empty, and optimize-merge-admin-levels right after index-admin-levels-hierarchy, so the two other indexes are built once, over the rows that stay. no index stage deletes or folds on its own.

query

$ geolite query "-23.970949,-46.318730"                                         # the base of the country whose boundary holds the point
$ geolite query "rua castro alves, embare, santos, sao paulo"                   # every base of the data path at once
$ geolite query "rua castro alves, embare, santos, sao paulo" --countries br   # the bases named

explore

$ geolite http-server   # open http://localhost:8080
$ geolite tui           # the admin levels walked like folders, one per country at the root

run the end-to-end suite

$ cargo test --profile e2e --test '*' -- --ignored --nocapture

question and answers

a) why geolite?

"geo" comes from "geocode" and "lite" comes from "sqlite", no special meaning.

b) where does the data come from?

the data comes from any .osm.pbf file (openstreetmap's protobuffer format). this project uses geofabrik as the initial source, which extracts its data from openstreetmap.

c) which license applies?

the source code is under agplv3 and its dependencies keep their own (all permissive: mit, apache-2.0, bsd, zlib, isc). databases built from openstreetmap data — including the ones shipped in the prebuilt-* images — are derivative databases under the odbl, filtered and restructured for geocoding: © openstreetmap contributors.

d) why build another geocoder?

two reasons, in this order: to practice rust on a problem large enough to be interesting, and because the alternatives i tried were a bit too complex for a quick run.

license: GNU AGPLv3


this is a work in progress and, for now, new patch versions have no backward-compatibility guarantees