]> git.openstreetmap.org Git - nominatim.git/blobdiff - docs/library/Getting-Started.md
Merge pull request #3593 from lonvia/order-by-bbox
[nominatim.git] / docs / library / Getting-Started.md
index 77724e67c7212d4d5b788d2d307a13156ae30dad..9f81724a155888b4e8174935fce372112f8d193f 100644 (file)
@@ -1,77 +1,76 @@
 # Getting Started
 
 # Getting Started
 
-The Nominatim search frontend can directly be used as a Python library in
-scripts and applications. When you have imported your own Nominatim database,
-then it is no longer necessary to run a full web service for it and access
-the database through http requests. With the Nominatim library it is possible
-to access all search functionality directly from your Python code. There are
-also less constraints on the kinds of data that can be accessed. The library
-allows to get access to more detailed information about the objects saved
-in the database.
-
-!!! danger
-    The library interface is currently in an experimental stage. There might
-    be some smaller adjustments to the public interface until the next version.
-
-    The library also misses a proper installation routine, so some manipulation
-    of the PYTHONPATH is required. Use is only recommended for advanced Python
-    programmers at the moment.
+The Nominatim search frontend is implemented as a Python library and can as
+such directly be used in Python scripts and applications. You don't need to
+set up a web frontend and access it through HTTP calls. The library gives
+direct access to the Nominatim database through similar search functions as
+offered by the web API. In addition, it will give you a more complete and
+detailed view on the search objects stored in the database.
+
+!!! warning
+
+    The Nominatim library is used for accessing a local Nominatim database.
+    It is not meant to be used against web services of Nominatim like the
+    one on https://nominatim.openstreetmap.org. If you need a Python library
+    to access these web services, have a look at
+    [GeoPy](https://geopy.readthedocs.io). Don't forget to consult the
+    usage policy of the service you want to use before accessing such
+    a web service.
 
 ## Installation
 
 To use the Nominatim library, you need access to a local Nominatim database.
 
 ## Installation
 
 To use the Nominatim library, you need access to a local Nominatim database.
-Follow the [installation and import instructions](../admin/) to set up your
-database.
+Follow the [installation](../admin/Installation.md) and
+[import](../admin/Import.md) instructions to set up your database.
 
 
-It is not yet possible to install it in the usual way via pip or inside a
-virtualenv. To get access to the library you need to set an appropriate
-PYTHONPATH. With the default installation, the python library can be found
-under `/usr/local/share/nominatim/lib-python`. If you have installed
-Nominatim under a different prefix, adapt the `/usr/local/` part accordingly.
-You can also point the PYTHONPATH to the Nominatim source code.
+The Nominatim frontend library is contained in the Python package `nominatim-api`.
+You can install the latest released version directly from pip:
 
 
-### A simple search example
+    pip install nominatim-api
+
+To install the package from the source tree directly, run:
+
+    pip install packaging/nominatim-api
+
+Usually you would want to run this in a virtual environment.
+
+## A simple search example
 
 To query the Nominatim database you need to first set up a connection. This
 is done by creating an Nominatim API object. This object exposes all the
 search functions of Nominatim that are also known from its web API.
 
 
 To query the Nominatim database you need to first set up a connection. This
 is done by creating an Nominatim API object. This object exposes all the
 search functions of Nominatim that are also known from its web API.
 
-This code snippet implements a simple search for the town if 'Brugge':
+This code snippet implements a simple search for the town of 'Brugge':
 
 !!! example
     === "NominatimAPIAsync"
         ``` python
 
 !!! example
     === "NominatimAPIAsync"
         ``` python
-        from pathlib import Path
         import asyncio
 
         import asyncio
 
-        import nominatim.api as napi
+        import nominatim_api as napi
 
         async def search(query):
 
         async def search(query):
-            api = napi.NominatimAPIAsync(Path('.'))
-
-            return await api.search(query)
+            async with napi.NominatimAPIAsync() as api:
+                return await api.search(query)
 
         results = asyncio.run(search('Brugge'))
         if not results:
             print('Cannot find Brugge')
         else:
 
         results = asyncio.run(search('Brugge'))
         if not results:
             print('Cannot find Brugge')
         else:
-            print(f'Found a place at {results[0].centroid.x},{results[1].centroid.y}')
+            print(f'Found a place at {results[0].centroid.x},{results[0].centroid.y}')
         ```
 
     === "NominatimAPI"
         ``` python
         ```
 
     === "NominatimAPI"
         ``` python
-        from pathlib import Path
-
-        import nominatim.api as napi
+        import nominatim_api as napi
 
 
-        api = napi.NominatimAPI(Path('.'))
-
-        results = api.search('Brugge')
+        with napi.NominatimAPI() as api:
+            results = api.search('Brugge')
 
         if not results:
             print('Cannot find Brugge')
         else:
 
         if not results:
             print('Cannot find Brugge')
         else:
-            print(f'Found a place at {results[0].centroid.x},{results[1].centroid.y}')
+            print(f'Found a place at {results[0].centroid.x},{results[0].centroid.y}')
         ```
 
 The Nominatim library is designed around
         ```
 
 The Nominatim library is designed around
@@ -83,13 +82,13 @@ significantly.
 For smaller scripts there is also a synchronous wrapper around the API. By
 using `NominatimAPI`, you get exactly the same interface using classic functions.
 
 For smaller scripts there is also a synchronous wrapper around the API. By
 using `NominatimAPI`, you get exactly the same interface using classic functions.
 
-The examples in this chapter will always show how work with both of the
-implementations. The documentation itself will refer usually only to
+The examples in this chapter will always show-case both
+implementations. The documentation itself will usually refer only to
 'Nominatim API class' when both flavours are meant. If a functionality is
 available only for the synchronous or asynchronous version, this will be
 explicitly mentioned.
 
 'Nominatim API class' when both flavours are meant. If a functionality is
 available only for the synchronous or asynchronous version, this will be
 explicitly mentioned.
 
-### Defining which database to use
+## Defining which database to use
 
 The [Configuration](../admin/Import.md#configuration-setup-in-env)
 section explains how Nominatim is configured using the
 
 The [Configuration](../admin/Import.md#configuration-setup-in-env)
 section explains how Nominatim is configured using the
@@ -98,76 +97,120 @@ The same configuration mechanism is used with the
 Nominatim API library. You should therefore be sure you are familiar with
 the section.
 
 Nominatim API library. You should therefore be sure you are familiar with
 the section.
 
-The constructor of the 'Nominatim API class' takes one mandatory parameter:
-the path to the [project directory](../admin/Import.md#creating-the-project-directory).
-You should have set up this directory as part of the Nominatim import.
-Any configuration found in the `.env` file in this directory will automatically
-used.
+There are three different ways, how configuration options can be set for
+a 'Nominatim API class'. When you have set up your Nominatim database, you
+have normally created a [project directory](../admin/Import.md#creating-the-project-directory)
+which stores the various configuration and customization files that Nominatim
+needs. You may pass the location of the project directory to your
+'Nominatim API class' constructor and it will read the .env file in the
+directory and set the configuration accordingly. Here is the simple search
+example, using the configuration from a pre-defined project directory in
+`/srv/nominatim-project`:
+
+!!! example
+    === "NominatimAPIAsync"
+        ``` python
+        import asyncio
+
+        import nominatim_api as napi
 
 
-The second way to configure your Nominatim setup is through environment variables.
-Normally, Nominatim will check the operating system environment. This can be
-overwritten by giving the constructor a dictionary of configuration parameters.
+        async def search(query):
+            async with napi.NominatimAPIAsync('/srv/nominatim-project') as api:
+                return await api.search(query)
 
 
-Let us look up 'Brugge' in the special database named 'belgium' instead of the
-standard 'nominatim' database:
+        results = asyncio.run(search('Brugge'))
+        if not results:
+            print('Cannot find Brugge')
+        else:
+            print(f'Found a place at {results[0].centroid.x},{results[0].centroid.y}')
+        ```
+
+    === "NominatimAPI"
+        ``` python
+        import nominatim_api as napi
+
+        with napi.NominatimAPI('/srv/nominatim-project') as api:
+            results = api.search('Brugge')
+
+        if not results:
+            print('Cannot find Brugge')
+        else:
+            print(f'Found a place at {results[0].centroid.x},{results[0].centroid.y}')
+        ```
+
+
+You may also configure Nominatim by setting environment variables.
+Normally Nominatim will check the operating system environment. Lets
+say you want to look up 'Brugge' in the special database named 'belgium' instead of the
+standard 'nominatim' database. You can run the example script above like this:
+
+```
+NOMINATIM_DATABASE_DSN=pgsql:dbname=belgium python3 example.py
+```
+
+The third option to configure the library is to hand in the configuration
+parameters into the 'Nominatim API class'. Changing the database would look
+like this:
 
 !!! example
     === "NominatimAPIAsync"
         ``` python
 
 !!! example
     === "NominatimAPIAsync"
         ``` python
-        from pathlib import Path
         import asyncio
         import asyncio
-
-        import nominatim.api as napi
+        import nominatim_api as napi
 
         config_params = {
             'NOMINATIM_DATABASE_DSN': 'pgsql:dbname=belgium'
         }
 
         async def search(query):
 
         config_params = {
             'NOMINATIM_DATABASE_DSN': 'pgsql:dbname=belgium'
         }
 
         async def search(query):
-            api = napi.NominatimAPIAsync(Path('.'), environ=config_params)
-
-            return await api.search(query)
+            async with napi.NominatimAPIAsync(environ=config_params) as api:
+                return await api.search(query)
 
         results = asyncio.run(search('Brugge'))
         ```
 
     === "NominatimAPI"
         ``` python
 
         results = asyncio.run(search('Brugge'))
         ```
 
     === "NominatimAPI"
         ``` python
-        from pathlib import Path
-
-        import nominatim.api as napi
+        import nominatim_api as napi
 
         config_params = {
             'NOMINATIM_DATABASE_DSN': 'pgsql:dbname=belgium'
         }
 
 
         config_params = {
             'NOMINATIM_DATABASE_DSN': 'pgsql:dbname=belgium'
         }
 
-        api = napi.NominatimAPI(Path('.'), environ=config_params)
-
-        results = api.search('Brugge')
+        with napi.NominatimAPI(environ=config_params) as api:
+            results = api.search('Brugge')
         ```
 
         ```
 
-### Presenting results to humans
+When the `environ` parameter is given, then only configuration variables
+from this dictionary will be used. The operating system's environment
+variables will be ignored.
 
 
-All search functions return the raw results from the database. There is no
-full human-readable label. To create such a label, you need two things:
+## Presenting results to humans
+
+All search functions return full result objects from the database. Such a
+result object contains lots of details: names, address information, OSM tags etc.
+This gives you lots of flexibility what to do with the results.
+
+One of the most common things to get is some kind of human-readable label
+that describes the result in a compact form. Usually this would be the name
+of the object and some parts of the address to explain where in the world
+it is. To create such a label, you need two things:
 
 * the address details of the place
 
 * the address details of the place
-* adapt the result to the language you wish to use for display
+* all names for the label adapted to the language you wish to use for display
 
 Again searching for 'Brugge', this time with a nicely formatted result:
 
 !!! example
     === "NominatimAPIAsync"
         ``` python
 
 Again searching for 'Brugge', this time with a nicely formatted result:
 
 !!! example
     === "NominatimAPIAsync"
         ``` python
-        from pathlib import Path
         import asyncio
 
         import asyncio
 
-        import nominatim.api as napi
+        import nominatim_api as napi
 
         async def search(query):
 
         async def search(query):
-            api = napi.NominatimAPIAsync(Path('.'))
-
-            return await api.search(query, address_details=True)
+            async with napi.NominatimAPIAsync() as api:
+                return await api.search(query, address_details=True)
 
         results = asyncio.run(search('Brugge'))
 
 
         results = asyncio.run(search('Brugge'))
 
@@ -179,13 +222,10 @@ Again searching for 'Brugge', this time with a nicely formatted result:
 
     === "NominatimAPI"
         ``` python
 
     === "NominatimAPI"
         ``` python
-        from pathlib import Path
-
-        import nominatim.api as napi
-
-        api = napi.NominatimAPI(Path('.'))
+        import nominatim_api as napi
 
 
-        results = api.search('Brugge', address_details=True)
+        with napi.NominatimAPI() as api:
+            results = api.search('Brugge', address_details=True)
 
         locale = napi.Locales(['fr', 'en'])
         for i, result in enumerate(results):
 
         locale = napi.Locales(['fr', 'en'])
         for i, result in enumerate(results):
@@ -209,8 +249,8 @@ results should be presented. As with the names in the result itself, the
 places in `address_rows` contain all possible name translation for each row.
 
 The library has a helper class `Locale` which helps extracting a name of a
 places in `address_rows` contain all possible name translation for each row.
 
 The library has a helper class `Locale` which helps extracting a name of a
-place in the preferred language. It gets a list of language code in the
-order of preference. So
+place in the preferred language. It takes a single parameter with a list
+of language codes in the order of preference. So
 
 ``` python
 locale = napi.Locale(['fr', 'en'])
 
 ``` python
 locale = napi.Locale(['fr', 'en'])
@@ -220,7 +260,7 @@ creates a helper class that returns the name preferably in French. If that is
 not possible, it tries English and eventually falls back to the default `name`
 or `ref`.
 
 not possible, it tries English and eventually falls back to the default `name`
 or `ref`.
 
-The Locale object can be applied to a name dictionary to return the best-matching
+The `Locale` object can be applied to a name dictionary to return the best-matching
 name out of it:
 
 ``` python
 name out of it:
 
 ``` python
@@ -241,7 +281,7 @@ Bruges, Flandre-Occidentale, Flandre, Belgique
 
 This is a fairly simple way to create a human-readable description. The
 place information in `address_rows` contains further information about each
 
 This is a fairly simple way to create a human-readable description. The
 place information in `address_rows` contains further information about each
-place. For example, which OSM `adlin_level` was used, what category the place
+place. For example, which OSM `admin_level` was used, what category the place
 belongs to or what rank Nominatim has assigned. Use this to adapt the output
 to local address formats.
 
 belongs to or what rank Nominatim has assigned. Use this to adapt the output
 to local address formats.