]> git.openstreetmap.org Git - nominatim.git/blob - docs/admin/Tokenizers.md
Merge pull request #2428 from lonvia/rename-icu-tokenizer
[nominatim.git] / docs / admin / Tokenizers.md
1 # Tokenizers
2
3 The tokenizer module in Nominatim is responsible for analysing the names given
4 to OSM objects and the terms of an incoming query in order to make sure, they
5 can be matched appropriately.
6
7 Nominatim offers different tokenizer modules, which behave differently and have
8 different configuration options. This sections describes the tokenizers and how
9 they can be configured.
10
11 !!! important
12     The use of a tokenizer is tied to a database installation. You need to choose
13     and configure the tokenizer before starting the initial import. Once the import
14     is done, you cannot switch to another tokenizer anymore. Reconfiguring the
15     chosen tokenizer is very limited as well. See the comments in each tokenizer
16     section.
17
18 ## Legacy tokenizer
19
20 The legacy tokenizer implements the analysis algorithms of older Nominatim
21 versions. It uses a special Postgresql module to normalize names and queries.
22 This tokenizer is currently the default.
23
24 To enable the tokenizer add the following line to your project configuration:
25
26 ```
27 NOMINATIM_TOKENIZER=legacy
28 ```
29
30 The Postgresql module for the tokenizer is available in the `module` directory
31 and also installed with the remainder of the software under
32 `lib/nominatim/module/nominatim.so`. You can specify a custom location for
33 the module with
34
35 ```
36 NOMINATIM_DATABASE_MODULE_PATH=<path to directory where nominatim.so resides>
37 ```
38
39 This is in particular useful when the database runs on a different server.
40 See [Advanced installations](Advanced-Installations.md#importing-nominatim-to-an-external-postgresql-database) for details.
41
42 There are no other configuration options for the legacy tokenizer. All
43 normalization functions are hard-coded.
44
45 ## ICU tokenizer
46
47 !!! danger
48     This tokenizer is currently in active development and still subject
49     to backwards-incompatible changes.
50
51 The ICU tokenizer uses the [ICU library](http://site.icu-project.org/) to
52 normalize names and queries. It also offers configurable decomposition and
53 abbreviation handling.
54
55 To enable the tokenizer add the following line to your project configuration:
56
57 ```
58 NOMINATIM_TOKENIZER=icu
59 ```
60
61 ### How it works
62
63 On import the tokenizer processes names in the following four stages:
64
65 1. The **Normalization** part removes all non-relevant information from the
66    input.
67 2. Incoming names are now converted to **full names**. This process is currently
68    hard coded and mostly serves to handle name tags from OSM that contain
69    multiple names (e.g. [Biel/Bienne](https://www.openstreetmap.org/node/240097197)).
70 3. Next the tokenizer creates **variants** from the full names. These variants
71    cover decomposition and abbreviation handling. Variants are saved to the
72    database, so that it is not necessary to create the variants for a search
73    query.
74 4. The final **Tokenization** step converts the names to a simple ASCII form,
75    potentially removing further spelling variants for better matching.
76
77 At query time only stage 1) and 4) are used. The query is normalized and
78 tokenized and the resulting string used for searching in the database.
79
80 ### Configuration
81
82 The ICU tokenizer is configured using a YAML file which can be configured using
83 `NOMINATIM_TOKENIZER_CONFIG`. The configuration is read on import and then
84 saved as part of the internal database status. Later changes to the variable
85 have no effect.
86
87 Here is an example configuration file:
88
89 ``` yaml
90 normalization:
91     - ":: lower ()"
92     - "ß > 'ss'" # German szet is unimbigiously equal to double ss
93 transliteration:
94     - !include /etc/nominatim/icu-rules/extended-unicode-to-asccii.yaml
95     - ":: Ascii ()"
96 variants:
97     - language: de
98       words:
99         - ~haus => haus
100         - ~strasse -> str
101     - language: en
102       words: 
103         - road -> rd
104         - bridge -> bdge,br,brdg,bri,brg
105 ```
106
107 The configuration file contains three sections:
108 `normalization`, `transliteration`, `variants`.
109
110 The normalization and transliteration sections each must contain a list of
111 [ICU transformation rules](https://unicode-org.github.io/icu/userguide/transforms/general/rules.html).
112 The rules are applied in the order in which they appear in the file.
113 You can also include additional rules from external yaml file using the
114 `!include` tag. The included file must contain a valid YAML list of ICU rules
115 and may again include other files.
116
117 !!! warning
118     The ICU rule syntax contains special characters that conflict with the
119     YAML syntax. You should therefore always enclose the ICU rules in
120     double-quotes.
121
122 The variants section defines lists of replacements which create alternative
123 spellings of a name. To create the variants, a name is scanned from left to
124 right and the longest matching replacement is applied until the end of the
125 string is reached.
126
127 The variants section must contain a list of replacement groups. Each group
128 defines a set of properties that describes where the replacements are
129 applicable. In addition, the word section defines the list of replacements
130 to be made. The basic replacement description is of the form:
131
132 ```
133 <source>[,<source>[...]] => <target>[,<target>[...]]
134 ```
135
136 The left side contains one or more `source` terms to be replaced. The right side
137 lists one or more replacements. Each source is replaced with each replacement
138 term.
139
140 !!! tip
141     The source and target terms are internally normalized using the
142     normalization rules given in the configuration. This ensures that the
143     strings match as expected. In fact, it is better to use unnormalized
144     words in the configuration because then it is possible to change the
145     rules for normalization later without having to adapt the variant rules.
146
147 #### Decomposition
148
149 In its standard form, only full words match against the source. There
150 is a special notation to match the prefix and suffix of a word:
151
152 ``` yaml
153 - ~strasse => str  # matches "strasse" as full word and in suffix position
154 - hinter~ => hntr  # matches "hinter" as full word and in prefix position
155 ```
156
157 There is no facility to match a string in the middle of the word. The suffix
158 and prefix notation automatically trigger the decomposition mode: two variants
159 are created for each replacement, one with the replacement attached to the word
160 and one separate. So in above example, the tokenization of "hauptstrasse" will
161 create the variants "hauptstr" and "haupt str". Similarly, the name "rote strasse"
162 triggers the variants "rote str" and "rotestr". By having decomposition work
163 both ways, it is sufficient to create the variants at index time. The variant
164 rules are not applied at query time.
165
166 To avoid automatic decomposition, use the '|' notation:
167
168 ``` yaml
169 - ~strasse |=> str
170 ```
171
172 simply changes "hauptstrasse" to "hauptstr" and "rote strasse" to "rote str".
173
174 #### Initial and final terms
175
176 It is also possible to restrict replacements to the beginning and end of a
177 name:
178
179 ``` yaml
180 - ^south => s  # matches only at the beginning of the name
181 - road$ => rd  # matches only at the end of the name
182 ```
183
184 So the first example would trigger a replacement for "south 45th street" but
185 not for "the south beach restaurant".
186
187 #### Replacements vs. variants
188
189 The replacement syntax `source => target` works as a pure replacement. It changes
190 the name instead of creating a variant. To create an additional version, you'd
191 have to write `source => source,target`. As this is a frequent case, there is
192 a shortcut notation for it:
193
194 ```
195 <source>[,<source>[...]] -> <target>[,<target>[...]]
196 ```
197
198 The simple arrow causes an additional variant to be added. Note that
199 decomposition has an effect here on the source as well. So a rule
200
201 ``` yaml
202 - "~strasse -> str"
203 ```
204
205 means that for a word like `hauptstrasse` four variants are created:
206 `hauptstrasse`, `haupt strasse`, `hauptstr` and `haupt str`.
207
208 ### Reconfiguration
209
210 Changing the configuration after the import is currently not possible, although
211 this feature may be added at a later time.