]> git.openstreetmap.org Git - nominatim.git/blob - docs/develop/Database-Layout.md
docs: clarify role of placex table in search pipeline
[nominatim.git] / docs / develop / Database-Layout.md
1 # Database Layout
2
3 ### Import tables
4
5 OSM data is initially imported using [osm2pgsql](https://osm2pgsql.org).
6 Nominatim uses a custom flex style to create the initial import tables.
7
8 The import process creates the following tables:
9
10 ![osm2pgsql tables](osm2pgsql-tables.svg)
11
12 The `planet_osm_*` tables are the usual backing tables for OSM data. Note
13 that Nominatim uses them to look up special relations and to find nodes on
14 ways. Apart from those the osm2pgsql import produces three tables as output.
15
16 The **place_postcode** table collects postcode information that is not
17 already present on an object in the place table. That is for one thing
18 [postcode area relations](https://wiki.openstreetmap.org/wiki/Tag:boundary%3Dpostal_code)
19 and for another objects with a postcode tag but no other tagging that
20 qualifies it for inclusion into the geocoding database.
21
22 The table has the following fields:
23
24  * `osm_type` - kind of OSM object (**N** - node, **W** - way, **R** - relation)
25  * `osm_id` - original OSM ID
26  * `postcode` - postcode as extacted from the `postcal_code` tag
27  * `country_code` - computed country code for this postcode. This field
28    functions as a cache and is only computed when the table is used for
29    the computation of the final postcodes.
30  * `centroid` - centroid of the object
31  * `geometry` - the full geometry of the area for postcode areas only
32
33 The **place_interpolation** table holds all
34 [address interpolation lines](https://wiki.openstreetmap.org/wiki/Addresses#Interpolation)
35 and has the following fields:
36
37  * `osm_id` - original OSM ID
38  * `type` - type of interpolation as extracted from the `addr:interpolation` tag
39  * `address` - any other `addr:*` tags
40  * `nodes` - list of OSM nodes contained in this interpolation,
41     needed to compute the involved housenumbers later
42  * `geometry` - the linestring for the interpolation (in WSG84)
43
44 The **place** table holds all other OSM object that are interesting and
45 has the following fields:
46
47  * `osm_type` - kind of OSM object (**N** - node, **W** - way, **R** - relation)
48  * `osm_id` - original OSM ID
49  * `class` - key of principal tag defining the object type
50  * `type` - value of principal tag defining the object type
51  * `name` - collection of tags that contain a name or reference
52  * `admin_level` - numerical value of the tagged administrative level
53  * `address` - collection of tags defining the address of an object
54  * `extratags` - collection of additional interesting tags that are not
55                  directly relevant for searching
56  * `geometry` - geometry of the object (in WGS84)
57
58 A single OSM object may appear multiple times in this table when it is tagged
59 with multiple tags that may constitute a principal tag. Take for example a
60 motorway bridge. In OSM, this would be a way which is tagged with
61 `highway=motorway` and `bridge=yes`. This way would appear in the `place` table
62 once with `class` of `highway` and once with a `class` of `bridge`. Thus the
63 *unique key* for `place` is (`osm_type`, `osm_id`, `class`).
64
65 How raw OSM tags are mapped to the columns in the place table is to a certain
66 degree configurable. See [Customizing Import Styles](../customize/Import-Styles.md)
67 for more information.
68
69 ### Search tables
70
71 The following tables carry all information needed to do the search:
72
73 ![search tables](search-tables.svg)
74
75 The **placex** table is the central table that saves all information about the
76 searchable places in Nominatim. 
77
78 In simpler terms, the `placex` table can be seen as the final, processed version of OSM data that is ready for search.
79 While the `place` table contains raw imported data, `placex` stores enriched and indexed data that includes ranking, hierarchy (parent-child relationships), and computed metadata such as importance and postcode.
80 Most search queries in Nominatim ultimately read from this table, making it the core table for forward and reverse geocoding.
81
82 The basic columns are the same as for the
83 place table and have the same meaning. The placex tables adds the following
84 additional columns:
85
86  * `place_id` - the internal unique ID to identify the place
87  * `partition` - the id to use with partitioned tables (see below)
88  * `geometry_sector` - a location hash used for geographically close ordering
89  * `parent_place_id` - the next higher place in the address hierarchy, only
90    relevant for POI-type places (with rank 30)
91  * `linked_place_id` - place ID of the place this object has been merged with.
92    When this ID is set, then the place is invisible for search.
93  * `importance` - measure how well known the place is
94  * `rank_search`, `rank_address` - search and address rank (see [Customizing ranking](../customize/Ranking.md)
95  * `wikipedia` - the wikipedia page used for computing the importance of the place
96  * `country_code` - the country the place is located in
97  * `housenumber` - normalized housenumber, if the place has one
98  * `postcode` - computed postcode for the place
99  * `indexed_status` - processing status of the place (0 - ready, 1 - freshly inserted, 2 - needs updating, 100 - needs deletion)
100  * `indexed_date` - timestamp when the place was processed last
101  * `centroid` - a point feature for the place
102  * `token_info` - a dummy field used to inject information from the tokenizer
103    into the indexing process
104
105 For implementation details, see the SQL definition in `lib-sql/tables/placex.sql` and the SQLAlchemy schema in `src/nominatim_api/sql/sqlalchemy_schema.py`.
106
107 The **location_property_osmline** table is a special table for
108 [address interpolations](https://wiki.openstreetmap.org/wiki/Addresses#Using_interpolation).
109 The columns have the same meaning and use as the columns with the same name in
110 the placex table. Only the following columns are special:
111
112  * `startnumber`, `endnumber` and `step` - beginning and end of the number range
113     for the interpolation and the increment steps
114  * `type` - a string to indicate the interval between the numbers as imported
115    from the OSM `addr:interpolation` tag; valid values are `odd`, `even`, `all`
116    or a single digit number; interpolations with other values are silently
117    dropped
118
119 Address interpolations are always ways in OSM, which is why there is no column
120 `osm_type`.
121
122 The **location_postcodes** table holds computed postcode assembled from the
123 postcode information available in OSM. When a postcode has a postcode area
124 relation, then the table stores its full geometry. For all other postcode
125 the centroid is computed using the position of all OSM object that reference
126 the same postoce. The `osm_id` field can be used to distinguish the two.
127 When set, it refers to the OSM relation with the postcode area.
128 The meaning of the columns in the table is again the same as that of the
129 placex table.
130
131 Every place needs an address, a set of surrounding places that describe the
132 location of the place. The set of address places is made up of OSM places
133 themselves. The **place_addressline** table cross-references for each place
134 all the places that make up its address. Two columns define the address
135 relation:
136
137   * `place_id` - reference to the place being addressed
138   * `address_place_id` - reference to the place serving as an address part
139
140 The most of the columns cache information from the placex entry of the address
141 part. The exceptions are:
142
143   * `fromarea` - is true if the address part has an area geometry and can
144     therefore be considered preceise
145   * `isaddress` - is true if the address part should show up in the address
146     output. Sometimes there are multiple places competing for for same address
147     type (e.g. multiple cities) and this field resolves the tie.
148
149 The **search_name** table contains the search index proper. It saves for each
150 place the terms with which the place can be found. The terms are split into
151 the name itself and all terms that make up the address. The table mirrors some
152 of the columns from placex for faster lookup.
153
154 Search terms are not saved as strings. Each term is assigned an integer and those
155 integers are saved in the name and address vectors of the search_name table. The
156 **word** table serves as the lookup table from string to such a word ID. The
157 exact content of the word table depends on the [tokenizer](Tokenizers.md) used.
158
159 ## Address computation tables
160
161 Next to the main search tables, there is a set of secondary helper tables used
162 to compute the address relations between places. These tables are partitioned.
163 Each country is assigned a partition number in the country_name table (see
164 below) and the data is then split between a set of tables, one for each
165 partition. Note that Nominatim still manually manages partitioned tables.
166 Native support for partitions in PostgreSQL only became usable with version 13.
167 It will be a little while before Nominatim drops support for older versions.
168
169 ![address tables](address-tables.svg)
170
171 The **search_name_X** tables are used to look up streets that appear in the
172 `addr:street` tag.
173
174 The **location_area_large_X** tables are used to look up larger areas
175 (administrative boundaries and place nodes) either through their geographic
176 closeness or through `addr:*` entries.
177
178 The **location_road_X** tables are used to find the closest street for a
179 dependent place.
180
181 All three table cache specific information from the placex table for their
182 selected subset of places:
183
184  * `keywords` and `name_vector` contain lists of term ids (from the word table)
185    that the full name of the place should match against
186  * `isguess` is true for places that are not described by an area
187
188 All other columns reflect their counterpart in the placex table.
189
190 ## Static data tables
191
192 Nominatim also creates a number of static tables at import:
193
194  * `nominatim_properties` saves settings that must not be changed after
195     import
196  * `address_levels` save the rank information from the
197    [ranking configuration](../customize/Ranking.md)
198  * `country_name` contains a fallback of names for all countries, their
199    default languages and saves the assignment of countries to partitions.
200  * `country_osm_grid` provides a fallback for country geometries
201
202 ## Auxiliary data tables
203
204 Finally there are some table for auxiliary data:
205
206  * `location_property_tiger` - saves housenumber from the Tiger import. Its
207    layout is similar to that of `location_propoerty_osmline`.
208  * `place_class_*` tables are helper tables to facilitate lookup of POIs
209    by their class and type. They exist because it is not possible to create
210    combined indexes with geometries.
211