mirror of
https://github.com/osm-search/Nominatim.git
synced 2026-03-07 10:34:08 +00:00
Compare commits
16 Commits
docs-5.2.x
...
922667b650
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
922667b650 | ||
|
|
fba803167c | ||
|
|
782df52ea0 | ||
|
|
c36da68a48 | ||
|
|
716de13bc9 | ||
|
|
1df56d7548 | ||
|
|
9cfef7a31a | ||
|
|
139678f367 | ||
|
|
e578c60ff4 | ||
|
|
7b4a3c8500 | ||
|
|
7751f9a6b6 | ||
|
|
303ac42b47 | ||
|
|
6a2d2daad5 | ||
|
|
a51c771107 | ||
|
|
55547723bf | ||
|
|
362088775f |
@@ -110,17 +110,14 @@ Then you can install Nominatim with:
|
|||||||
|
|
||||||
pip install nominatim-db nominatim-api
|
pip install nominatim-db nominatim-api
|
||||||
|
|
||||||
## Downloading and building Nominatim from source
|
## Downloading and building Nominatim
|
||||||
|
|
||||||
The following instructions are only relevant, if you want to build and
|
|
||||||
install Nominatim **from source**.
|
|
||||||
|
|
||||||
### Downloading the latest release
|
### Downloading the latest release
|
||||||
|
|
||||||
You can download the [latest release from nominatim.org](https://nominatim.org/downloads/).
|
You can download the [latest release from nominatim.org](https://nominatim.org/downloads/).
|
||||||
The release contains all necessary files. Just unpack it.
|
The release contains all necessary files. Just unpack it.
|
||||||
|
|
||||||
### Downloading the source for the latest development version
|
### Downloading the latest development version
|
||||||
|
|
||||||
If you want to install latest development version from github:
|
If you want to install latest development version from github:
|
||||||
|
|
||||||
@@ -134,7 +131,7 @@ The development version does not include the country grid. Download it separatel
|
|||||||
wget -O Nominatim/data/country_osm_grid.sql.gz https://nominatim.org/data/country_grid.sql.gz
|
wget -O Nominatim/data/country_osm_grid.sql.gz https://nominatim.org/data/country_grid.sql.gz
|
||||||
```
|
```
|
||||||
|
|
||||||
### Building Nominatim from source
|
### Building Nominatim
|
||||||
|
|
||||||
Nominatim is easiest to run from its own virtual environment. To create one, run:
|
Nominatim is easiest to run from its own virtual environment. To create one, run:
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,15 @@ To run the functional tests, do
|
|||||||
|
|
||||||
pytest test/bdd
|
pytest test/bdd
|
||||||
|
|
||||||
|
You can run a single feature file using expression matching:
|
||||||
|
|
||||||
|
pytest test/bdd -k osm2pgsql/import/entrances.feature
|
||||||
|
|
||||||
|
This even works for running single tests by adding the line number of the
|
||||||
|
scenario header like that:
|
||||||
|
|
||||||
|
pytest test/bdd -k 'osm2pgsql/import/entrances.feature and L4'
|
||||||
|
|
||||||
The BDD tests create databases for the tests. You can set name of the databases
|
The BDD tests create databases for the tests. You can set name of the databases
|
||||||
through configuration variables in your `pytest.ini`:
|
through configuration variables in your `pytest.ini`:
|
||||||
|
|
||||||
|
|||||||
@@ -321,7 +321,6 @@ module.NAME_TAGS = {}
|
|||||||
|
|
||||||
module.NAME_TAGS.core = {main = {'name', 'name:*',
|
module.NAME_TAGS.core = {main = {'name', 'name:*',
|
||||||
'int_name', 'int_name:*',
|
'int_name', 'int_name:*',
|
||||||
'nat_name', 'nat_name:*',
|
|
||||||
'reg_name', 'reg_name:*',
|
'reg_name', 'reg_name:*',
|
||||||
'loc_name', 'loc_name:*',
|
'loc_name', 'loc_name:*',
|
||||||
'old_name', 'old_name:*',
|
'old_name', 'old_name:*',
|
||||||
|
|||||||
@@ -341,6 +341,22 @@ BEGIN
|
|||||||
END IF;
|
END IF;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
|
IF bnd.extratags ? 'wikidata' THEN
|
||||||
|
FOR linked_placex IN
|
||||||
|
SELECT * FROM placex
|
||||||
|
WHERE placex.class = 'place' AND placex.osm_type = 'N'
|
||||||
|
AND placex.extratags ? 'wikidata' -- needed to select right index
|
||||||
|
AND placex.extratags->'wikidata' = bnd.extratags->'wikidata'
|
||||||
|
AND (placex.linked_place_id is null or placex.linked_place_id = bnd.place_id)
|
||||||
|
AND placex.rank_search < 26
|
||||||
|
AND _st_covers(bnd.geometry, placex.geometry)
|
||||||
|
ORDER BY lower(name->'name') = bnd_name desc
|
||||||
|
LOOP
|
||||||
|
{% if debug %}RAISE WARNING 'Found wikidata-matching place node %', linked_placex.osm_id;{% endif %}
|
||||||
|
RETURN linked_placex;
|
||||||
|
END LOOP;
|
||||||
|
END IF;
|
||||||
|
|
||||||
-- If extratags has a place tag, look for linked nodes by their place type.
|
-- If extratags has a place tag, look for linked nodes by their place type.
|
||||||
-- Area and node still have to have the same name.
|
-- Area and node still have to have the same name.
|
||||||
IF bnd.extratags ? 'place' and bnd.extratags->'place' != 'postcode'
|
IF bnd.extratags ? 'place' and bnd.extratags->'place' != 'postcode'
|
||||||
@@ -361,22 +377,6 @@ BEGIN
|
|||||||
END LOOP;
|
END LOOP;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
IF bnd.extratags ? 'wikidata' THEN
|
|
||||||
FOR linked_placex IN
|
|
||||||
SELECT * FROM placex
|
|
||||||
WHERE placex.class = 'place' AND placex.osm_type = 'N'
|
|
||||||
AND placex.extratags ? 'wikidata' -- needed to select right index
|
|
||||||
AND placex.extratags->'wikidata' = bnd.extratags->'wikidata'
|
|
||||||
AND (placex.linked_place_id is null or placex.linked_place_id = bnd.place_id)
|
|
||||||
AND placex.rank_search < 26
|
|
||||||
AND _st_covers(bnd.geometry, placex.geometry)
|
|
||||||
ORDER BY lower(name->'name') = bnd_name desc
|
|
||||||
LOOP
|
|
||||||
{% if debug %}RAISE WARNING 'Found wikidata-matching place node %', linked_placex.osm_id;{% endif %}
|
|
||||||
RETURN linked_placex;
|
|
||||||
END LOOP;
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
-- Name searches can be done for ways as well as relations
|
-- Name searches can be done for ways as well as relations
|
||||||
IF bnd_name is not null THEN
|
IF bnd_name is not null THEN
|
||||||
{% if debug %}RAISE WARNING 'Looking for nodes with matching names';{% endif %}
|
{% if debug %}RAISE WARNING 'Looking for nodes with matching names';{% endif %}
|
||||||
@@ -874,7 +874,7 @@ BEGIN
|
|||||||
-- Remove linkage, if we have computed a different new linkee.
|
-- Remove linkage, if we have computed a different new linkee.
|
||||||
UPDATE placex SET linked_place_id = null, indexed_status = 2
|
UPDATE placex SET linked_place_id = null, indexed_status = 2
|
||||||
WHERE linked_place_id = NEW.place_id
|
WHERE linked_place_id = NEW.place_id
|
||||||
and (linked_place is null or linked_place_id != linked_place);
|
and (linked_place is null or place_id != linked_place);
|
||||||
-- update not necessary for osmline, cause linked_place_id does not exist
|
-- update not necessary for osmline, cause linked_place_id does not exist
|
||||||
|
|
||||||
-- Postcodes are just here to compute the centroids. They are not searchable
|
-- Postcodes are just here to compute the centroids. They are not searchable
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
site_name: Nominatim 5.2.0 Manual
|
site_name: Nominatim Manual
|
||||||
theme:
|
theme:
|
||||||
font: false
|
font: false
|
||||||
name: material
|
name: material
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ Helper classes and functions for formatting results into API responses.
|
|||||||
from typing import Type, TypeVar, Dict, List, Callable, Any, Mapping, Optional, cast
|
from typing import Type, TypeVar, Dict, List, Callable, Any, Mapping, Optional, cast
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import importlib
|
import importlib.util
|
||||||
|
|
||||||
from .server.content_types import CONTENT_JSON
|
from .server.content_types import CONTENT_JSON
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
"""
|
"""
|
||||||
Server implementation using the falcon webserver framework.
|
Server implementation using the falcon webserver framework.
|
||||||
"""
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Optional, Mapping, Any, List, cast
|
from typing import Optional, Mapping, Any, List, cast
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import asyncio
|
import asyncio
|
||||||
@@ -161,7 +163,7 @@ class APIMiddleware:
|
|||||||
|
|
||||||
def __init__(self, project_dir: Path, environ: Optional[Mapping[str, str]]) -> None:
|
def __init__(self, project_dir: Path, environ: Optional[Mapping[str, str]]) -> None:
|
||||||
self.api = NominatimAPIAsync(project_dir, environ)
|
self.api = NominatimAPIAsync(project_dir, environ)
|
||||||
self.app: Optional[App] = None
|
self.app: Optional[App[Request, Response]] = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def config(self) -> Configuration:
|
def config(self) -> Configuration:
|
||||||
@@ -169,7 +171,7 @@ class APIMiddleware:
|
|||||||
"""
|
"""
|
||||||
return self.api.config
|
return self.api.config
|
||||||
|
|
||||||
def set_app(self, app: App) -> None:
|
def set_app(self, app: App[Request, Response]) -> None:
|
||||||
""" Set the Falcon application this middleware is connected to.
|
""" Set the Falcon application this middleware is connected to.
|
||||||
"""
|
"""
|
||||||
self.app = app
|
self.app = app
|
||||||
@@ -193,7 +195,7 @@ class APIMiddleware:
|
|||||||
|
|
||||||
|
|
||||||
def get_application(project_dir: Path,
|
def get_application(project_dir: Path,
|
||||||
environ: Optional[Mapping[str, str]] = None) -> App:
|
environ: Optional[Mapping[str, str]] = None) -> App[Request, Response]:
|
||||||
""" Create a Nominatim Falcon ASGI application.
|
""" Create a Nominatim Falcon ASGI application.
|
||||||
"""
|
"""
|
||||||
apimw = APIMiddleware(project_dir, environ)
|
apimw = APIMiddleware(project_dir, environ)
|
||||||
@@ -215,7 +217,7 @@ def get_application(project_dir: Path,
|
|||||||
return app
|
return app
|
||||||
|
|
||||||
|
|
||||||
def run_wsgi() -> App:
|
def run_wsgi() -> App[Request, Response]:
|
||||||
""" Entry point for uvicorn.
|
""" Entry point for uvicorn.
|
||||||
|
|
||||||
Make sure uvicorn is run from the project directory.
|
Make sure uvicorn is run from the project directory.
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ from ..tokenizer.base import AbstractTokenizer
|
|||||||
from ..version import NOMINATIM_VERSION
|
from ..version import NOMINATIM_VERSION
|
||||||
from .args import NominatimArgs
|
from .args import NominatimArgs
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
LOG = logging.getLogger()
|
LOG = logging.getLogger()
|
||||||
|
|
||||||
@@ -86,6 +87,8 @@ class SetupAll:
|
|||||||
from ..tools import database_import, postcodes, freeze
|
from ..tools import database_import, postcodes, freeze
|
||||||
from ..indexer.indexer import Indexer
|
from ..indexer.indexer import Indexer
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
num_threads = args.threads or psutil.cpu_count() or 1
|
num_threads = args.threads or psutil.cpu_count() or 1
|
||||||
country_info.setup_country_config(args.config)
|
country_info.setup_country_config(args.config)
|
||||||
|
|
||||||
@@ -138,6 +141,10 @@ class SetupAll:
|
|||||||
LOG.warning('Recompute word counts')
|
LOG.warning('Recompute word counts')
|
||||||
tokenizer.update_statistics(args.config, threads=num_threads)
|
tokenizer.update_statistics(args.config, threads=num_threads)
|
||||||
|
|
||||||
|
end_time = time.time()
|
||||||
|
elapsed = end_time - start_time
|
||||||
|
LOG.warning(f'Import completed successfully in {elapsed:.2f} seconds.')
|
||||||
|
|
||||||
self._finalize_database(args.config.get_libpq_dsn(), args.offline)
|
self._finalize_database(args.config.get_libpq_dsn(), args.offline)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ class CountryPostcodeMatcher:
|
|||||||
self.norm_pattern = re.compile(f'\\s*(?:{country_code.upper()}[ -]?)?({pc_pattern})\\s*')
|
self.norm_pattern = re.compile(f'\\s*(?:{country_code.upper()}[ -]?)?({pc_pattern})\\s*')
|
||||||
self.pattern = re.compile(pc_pattern)
|
self.pattern = re.compile(pc_pattern)
|
||||||
|
|
||||||
|
# We want to exclude 0000, 00-000, 000 00 etc
|
||||||
|
self.zero_pattern = re.compile(r'^[0\- ]+$')
|
||||||
|
|
||||||
self.output = config.get('output', r'\g<0>')
|
self.output = config.get('output', r'\g<0>')
|
||||||
|
|
||||||
def match(self, postcode: str) -> Optional[Match[str]]:
|
def match(self, postcode: str) -> Optional[Match[str]]:
|
||||||
@@ -40,7 +43,10 @@ class CountryPostcodeMatcher:
|
|||||||
normalized = self.norm_pattern.fullmatch(postcode.upper())
|
normalized = self.norm_pattern.fullmatch(postcode.upper())
|
||||||
|
|
||||||
if normalized:
|
if normalized:
|
||||||
return self.pattern.fullmatch(normalized.group(1))
|
match = self.pattern.fullmatch(normalized.group(1))
|
||||||
|
if match and self.zero_pattern.match(match.string):
|
||||||
|
return None
|
||||||
|
return match
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ Fixtures for BDD test steps
|
|||||||
"""
|
"""
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
|
import re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import psycopg
|
import psycopg
|
||||||
@@ -20,7 +21,8 @@ sys.path.insert(0, str(SRC_DIR / 'src'))
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from pytest_bdd.parsers import re as step_parse
|
from pytest_bdd.parsers import re as step_parse
|
||||||
from pytest_bdd import given, when, then
|
from pytest_bdd import given, when, then, scenario
|
||||||
|
from pytest_bdd.feature import get_features
|
||||||
|
|
||||||
pytest.register_assert_rewrite('utils')
|
pytest.register_assert_rewrite('utils')
|
||||||
|
|
||||||
@@ -373,3 +375,57 @@ def check_place_missing_lines(db_conn, table, osm_type, osm_id, osm_class):
|
|||||||
|
|
||||||
with db_conn.cursor() as cur:
|
with db_conn.cursor() as cur:
|
||||||
assert cur.execute(sql, params).fetchone()[0] == 0
|
assert cur.execute(sql, params).fetchone()[0] == 0
|
||||||
|
|
||||||
|
|
||||||
|
if pytest.version_tuple >= (8, 0, 0):
|
||||||
|
def pytest_pycollect_makemodule(module_path, parent):
|
||||||
|
return BddTestCollector.from_parent(parent, path=module_path)
|
||||||
|
|
||||||
|
|
||||||
|
class BddTestCollector(pytest.Module):
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
def collect(self):
|
||||||
|
for item in super().collect():
|
||||||
|
yield item
|
||||||
|
|
||||||
|
if hasattr(self.obj, 'PYTEST_BDD_SCENARIOS'):
|
||||||
|
for path in self.obj.PYTEST_BDD_SCENARIOS:
|
||||||
|
for feature in get_features([str(Path(self.path.parent, path).resolve())]):
|
||||||
|
yield FeatureFile.from_parent(self,
|
||||||
|
name=str(Path(path, feature.rel_filename)),
|
||||||
|
path=Path(feature.filename),
|
||||||
|
feature=feature)
|
||||||
|
|
||||||
|
|
||||||
|
# borrowed from pytest-bdd: src/pytest_bdd/scenario.py
|
||||||
|
def make_python_name(string: str) -> str:
|
||||||
|
"""Make python attribute name out of a given string."""
|
||||||
|
string = re.sub(r"\W", "", string.replace(" ", "_"))
|
||||||
|
return re.sub(r"^\d+_*", "", string).lower()
|
||||||
|
|
||||||
|
|
||||||
|
class FeatureFile(pytest.File):
|
||||||
|
class obj:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __init__(self, feature, **kwargs):
|
||||||
|
self.feature = feature
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
def collect(self):
|
||||||
|
for sname, sobject in self.feature.scenarios.items():
|
||||||
|
class_name = f"L{sobject.line_number}"
|
||||||
|
test_name = "test_" + make_python_name(sname)
|
||||||
|
|
||||||
|
@scenario(self.feature.filename, sname)
|
||||||
|
def _test():
|
||||||
|
pass
|
||||||
|
|
||||||
|
tclass = type(class_name, (),
|
||||||
|
{test_name: staticmethod(_test)})
|
||||||
|
setattr(self.obj, class_name, tclass)
|
||||||
|
|
||||||
|
yield pytest.Class.from_parent(self, name=class_name, obj=tclass)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import xml.etree.ElementTree as ET
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from pytest_bdd.parsers import re as step_parse
|
from pytest_bdd.parsers import re as step_parse
|
||||||
from pytest_bdd import scenarios, when, given, then
|
from pytest_bdd import when, given, then
|
||||||
|
|
||||||
from nominatim_db import cli
|
from nominatim_db import cli
|
||||||
from nominatim_db.config import Configuration
|
from nominatim_db.config import Configuration
|
||||||
@@ -150,4 +150,8 @@ def parse_api_json_response(api_response, fmt, num):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
scenarios('features/api')
|
if pytest.version_tuple >= (8, 0, 0):
|
||||||
|
PYTEST_BDD_SCENARIOS = ['features/api']
|
||||||
|
else:
|
||||||
|
from pytest_bdd import scenarios
|
||||||
|
scenarios('features/api')
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import re
|
|||||||
import psycopg
|
import psycopg
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from pytest_bdd import scenarios, when, then, given
|
from pytest_bdd import when, then, given
|
||||||
from pytest_bdd.parsers import re as step_parse
|
from pytest_bdd.parsers import re as step_parse
|
||||||
|
|
||||||
from utils.place_inserter import PlaceColumn
|
from utils.place_inserter import PlaceColumn
|
||||||
@@ -276,4 +276,8 @@ def then_check_interpolation_table_negative(db_conn, oid):
|
|||||||
assert cur.fetchone()[0] == 0
|
assert cur.fetchone()[0] == 0
|
||||||
|
|
||||||
|
|
||||||
scenarios('features/db')
|
if pytest.version_tuple >= (8, 0, 0):
|
||||||
|
PYTEST_BDD_SCENARIOS = ['features/db']
|
||||||
|
else:
|
||||||
|
from pytest_bdd import scenarios
|
||||||
|
scenarios('features/db')
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import asyncio
|
|||||||
import random
|
import random
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from pytest_bdd import scenarios, when, then, given
|
from pytest_bdd import when, then, given
|
||||||
from pytest_bdd.parsers import re as step_parse
|
from pytest_bdd.parsers import re as step_parse
|
||||||
|
|
||||||
from nominatim_db import cli
|
from nominatim_db import cli
|
||||||
@@ -106,4 +106,8 @@ def check_place_content(db_conn, datatable, node_grid, table, exact):
|
|||||||
check_table_content(db_conn, table, datatable, grid=node_grid, exact=bool(exact))
|
check_table_content(db_conn, table, datatable, grid=node_grid, exact=bool(exact))
|
||||||
|
|
||||||
|
|
||||||
scenarios('features/osm2pgsql')
|
if pytest.version_tuple >= (8, 0, 0):
|
||||||
|
PYTEST_BDD_SCENARIOS = ['features/osm2pgsql']
|
||||||
|
else:
|
||||||
|
from pytest_bdd import scenarios
|
||||||
|
scenarios('features/osm2pgsql')
|
||||||
|
|||||||
@@ -237,3 +237,9 @@ def test_postcode_default_pattern_pass(sanitize, postcode):
|
|||||||
@pytest.mark.sanitizer_params(convert_to_address=False, default_pattern='[A-Z0-9- ]{3,12}')
|
@pytest.mark.sanitizer_params(convert_to_address=False, default_pattern='[A-Z0-9- ]{3,12}')
|
||||||
def test_postcode_default_pattern_fail(sanitize, postcode):
|
def test_postcode_default_pattern_fail(sanitize, postcode):
|
||||||
assert sanitize(country='an', postcode=postcode) == []
|
assert sanitize(country='an', postcode=postcode) == []
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("postcode", ('00000', '00-000', 'PL-00000', 'PL 00-000'))
|
||||||
|
@pytest.mark.sanitizer_params(convert_to_address=False)
|
||||||
|
def test_postcode_zeros(sanitize, postcode):
|
||||||
|
assert sanitize(country='pl', postcode=postcode) == []
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export DEBIAN_FRONTEND=noninteractive #DOCS:
|
|||||||
libbz2-dev libpq-dev liblua5.3-dev lua5.3 lua-dkjson \
|
libbz2-dev libpq-dev liblua5.3-dev lua5.3 lua-dkjson \
|
||||||
nlohmann-json3-dev postgresql-14-postgis-3 \
|
nlohmann-json3-dev postgresql-14-postgis-3 \
|
||||||
postgresql-contrib-14 postgresql-14-postgis-3-scripts \
|
postgresql-contrib-14 postgresql-14-postgis-3-scripts \
|
||||||
libicu-dev virtualenv
|
libicu-dev virtualenv git
|
||||||
|
|
||||||
#
|
#
|
||||||
# System Configuration
|
# System Configuration
|
||||||
@@ -97,6 +97,23 @@ fi #DOCS:
|
|||||||
# Building and Configuration
|
# Building and Configuration
|
||||||
# --------------------------
|
# --------------------------
|
||||||
#
|
#
|
||||||
|
# Get the source code from Github and change into the source directory
|
||||||
|
#
|
||||||
|
if [ "x$1" == "xyes" ]; then #DOCS: :::sh
|
||||||
|
cd $USERHOME
|
||||||
|
git clone https://github.com/osm-search/Nominatim.git
|
||||||
|
cd Nominatim
|
||||||
|
else #DOCS:
|
||||||
|
cd $USERHOME/Nominatim #DOCS:
|
||||||
|
fi #DOCS:
|
||||||
|
|
||||||
|
# When installing the latest source from github, you also need to
|
||||||
|
# download the country grid:
|
||||||
|
|
||||||
|
if [ ! -f data/country_osm_grid.sql.gz ]; then #DOCS: :::sh
|
||||||
|
wget -O data/country_osm_grid.sql.gz https://nominatim.org/data/country_grid.sql.gz
|
||||||
|
fi #DOCS:
|
||||||
|
|
||||||
# Nominatim needs osm2pgsql >= 1.8. The version that comes with Ubuntu is
|
# Nominatim needs osm2pgsql >= 1.8. The version that comes with Ubuntu is
|
||||||
# too old. Download and compile your own:
|
# too old. Download and compile your own:
|
||||||
|
|
||||||
@@ -107,6 +124,7 @@ fi #DOCS:
|
|||||||
cmake ../osm2pgsql
|
cmake ../osm2pgsql
|
||||||
make
|
make
|
||||||
sudo make install
|
sudo make install
|
||||||
|
cd $USERHOME/Nominatim
|
||||||
|
|
||||||
# Nominatim should be installed in a separate Python virtual environment.
|
# Nominatim should be installed in a separate Python virtual environment.
|
||||||
# Create the virtual environment:
|
# Create the virtual environment:
|
||||||
@@ -119,7 +137,8 @@ fi #DOCS:
|
|||||||
|
|
||||||
# Now install Nominatim using pip:
|
# Now install Nominatim using pip:
|
||||||
|
|
||||||
$USERHOME/nominatim-venv/bin/pip install nominatim-db
|
cd $USERHOME/Nominatim
|
||||||
|
$USERHOME/nominatim-venv/bin/pip install packaging/nominatim-db
|
||||||
|
|
||||||
# Nominatim is now ready to use. You can continue with
|
# Nominatim is now ready to use. You can continue with
|
||||||
# [importing a database from OSM data](../admin/Import.md). If you want to set up
|
# [importing a database from OSM data](../admin/Import.md). If you want to set up
|
||||||
@@ -135,7 +154,9 @@ fi #DOCS:
|
|||||||
# To install all packages, run:
|
# To install all packages, run:
|
||||||
|
|
||||||
#DOCS:```sh
|
#DOCS:```sh
|
||||||
$USERHOME/nominatim-venv/bin/pip install falcon uvicorn gunicorn nominatim-api
|
$USERHOME/nominatim-venv/bin/pip install falcon uvicorn gunicorn
|
||||||
|
cd $USERHOME/Nominatim
|
||||||
|
$USERHOME/nominatim-venv/bin/pip install packaging/nominatim-api
|
||||||
#DOCS:```
|
#DOCS:```
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export DEBIAN_FRONTEND=noninteractive #DOCS:
|
|||||||
# Now you can install all packages needed for Nominatim:
|
# Now you can install all packages needed for Nominatim:
|
||||||
|
|
||||||
sudo apt-get install -y osm2pgsql postgresql-postgis postgresql-postgis-scripts \
|
sudo apt-get install -y osm2pgsql postgresql-postgis postgresql-postgis-scripts \
|
||||||
pkg-config libicu-dev virtualenv
|
pkg-config libicu-dev virtualenv git
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -94,6 +94,23 @@ fi #DOCS:
|
|||||||
# Building and Configuration
|
# Building and Configuration
|
||||||
# --------------------------
|
# --------------------------
|
||||||
#
|
#
|
||||||
|
# Get the source code from Github and change into the source directory
|
||||||
|
#
|
||||||
|
if [ "x$1" == "xyes" ]; then #DOCS: :::sh
|
||||||
|
cd $USERHOME
|
||||||
|
git clone https://github.com/osm-search/Nominatim.git
|
||||||
|
cd Nominatim
|
||||||
|
else #DOCS:
|
||||||
|
cd $USERHOME/Nominatim #DOCS:
|
||||||
|
fi #DOCS:
|
||||||
|
|
||||||
|
# When installing the latest source from github, you also need to
|
||||||
|
# download the country grid:
|
||||||
|
|
||||||
|
if [ ! -f data/country_osm_grid.sql.gz ]; then #DOCS: :::sh
|
||||||
|
wget -O data/country_osm_grid.sql.gz https://nominatim.org/data/country_grid.sql.gz
|
||||||
|
fi #DOCS:
|
||||||
|
|
||||||
# Nominatim should be installed in a separate Python virtual environment.
|
# Nominatim should be installed in a separate Python virtual environment.
|
||||||
# Create the virtual environment:
|
# Create the virtual environment:
|
||||||
|
|
||||||
@@ -105,7 +122,8 @@ fi #DOCS:
|
|||||||
|
|
||||||
# Now install Nominatim using pip:
|
# Now install Nominatim using pip:
|
||||||
|
|
||||||
$USERHOME/nominatim-venv/bin/pip install nominatim-db
|
cd $USERHOME/Nominatim
|
||||||
|
$USERHOME/nominatim-venv/bin/pip install packaging/nominatim-db
|
||||||
|
|
||||||
# Nominatim is now ready to use. The nominatim binary is available at
|
# Nominatim is now ready to use. The nominatim binary is available at
|
||||||
# `$USERHOME/venv/bin/nominatim`. If you want to have 'nominatim' in your
|
# `$USERHOME/venv/bin/nominatim`. If you want to have 'nominatim' in your
|
||||||
@@ -129,7 +147,9 @@ fi #DOCS:
|
|||||||
# To install all packages, run:
|
# To install all packages, run:
|
||||||
|
|
||||||
#DOCS:```sh
|
#DOCS:```sh
|
||||||
$USERHOME/nominatim-venv/bin/pip install falcon uvicorn gunicorn nominatim-api
|
$USERHOME/nominatim-venv/bin/pip install falcon uvicorn gunicorn
|
||||||
|
cd $USERHOME/Nominatim
|
||||||
|
$USERHOME/nominatim-venv/bin/pip install packaging/nominatim-api
|
||||||
#DOCS:```
|
#DOCS:```
|
||||||
|
|
||||||
# Next you need to create a systemd job that runs Nominatim on gunicorn.
|
# Next you need to create a systemd job that runs Nominatim on gunicorn.
|
||||||
|
|||||||
Reference in New Issue
Block a user