]> git.openstreetmap.org Git - nominatim.git/blob - docs/admin/Tokenizers.md
Merge pull request #2460 from lonvia/multiple-analyzers
[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 three stages:
64
65 1. During the **Sanitizer step** incoming names are cleaned up and converted to
66    **full names**. This step can be used to regularize spelling, split multi-name
67    tags into their parts and tag names with additional attributes. See the
68    [Sanitizers section](#sanitizers) below for available cleaning routines.
69 2. The **Normalization** part removes all information from the full names
70    that are not relevant for search.
71 3. The **Token analysis** step takes the normalized full names and creates
72    all transliterated variants under which the name should be searchable.
73    See the [Token analysis](#token-analysis) section below for more
74    information.
75
76 During query time, only normalization and transliteration are relevant.
77 An incoming query is first split into name chunks (this usually means splitting
78 the string at the commas) and the each part is normalised and transliterated.
79 The result is used to look up places in the search index.
80
81 ### Configuration
82
83 The ICU tokenizer is configured using a YAML file which can be configured using
84 `NOMINATIM_TOKENIZER_CONFIG`. The configuration is read on import and then
85 saved as part of the internal database status. Later changes to the variable
86 have no effect.
87
88 Here is an example configuration file:
89
90 ``` yaml
91 normalization:
92     - ":: lower ()"
93     - "ß > 'ss'" # German szet is unimbigiously equal to double ss
94 transliteration:
95     - !include /etc/nominatim/icu-rules/extended-unicode-to-asccii.yaml
96     - ":: Ascii ()"
97 sanitizers:
98     - step: split-name-list
99 token-analysis:
100     - analyzer: generic
101       variants:
102           - !include icu-rules/variants-ca.yaml
103           - words:
104               - road -> rd
105               - bridge -> bdge,br,brdg,bri,brg
106 ```
107
108 The configuration file contains four sections:
109 `normalization`, `transliteration`, `sanitizers` and `token-analysis`.
110
111 #### Normalization and Transliteration
112
113 The normalization and transliteration sections each define a set of
114 ICU rules that are applied to the names.
115
116 The **normalisation** rules are applied after sanitation. They should remove
117 any information that is not relevant for search at all. Usual rules to be
118 applied here are: lower-casing, removing of special characters, cleanup of
119 spaces.
120
121 The **transliteration** rules are applied at the end of the tokenization
122 process to transfer the name into an ASCII representation. Transliteration can
123 be useful to allow for further fuzzy matching, especially between different
124 scripts.
125
126 Each section must contain a list of
127 [ICU transformation rules](https://unicode-org.github.io/icu/userguide/transforms/general/rules.html).
128 The rules are applied in the order in which they appear in the file.
129 You can also include additional rules from external yaml file using the
130 `!include` tag. The included file must contain a valid YAML list of ICU rules
131 and may again include other files.
132
133 !!! warning
134     The ICU rule syntax contains special characters that conflict with the
135     YAML syntax. You should therefore always enclose the ICU rules in
136     double-quotes.
137
138 #### Sanitizers
139
140 The sanitizers section defines an ordered list of functions that are applied
141 to the name and address tags before they are further processed by the tokenizer.
142 They allows to clean up the tagging and bring it to a standardized form more
143 suitable for building the search index.
144
145 !!! hint
146     Sanitizers only have an effect on how the search index is built. They
147     do not change the information about each place that is saved in the
148     database. In particular, they have no influence on how the results are
149     displayed. The returned results always show the original information as
150     stored in the OpenStreetMap database.
151
152 Each entry contains information of a sanitizer to be applied. It has a
153 mandatory parameter `step` which gives the name of the sanitizer. Depending
154 on the type, it may have additional parameters to configure its operation.
155
156 The order of the list matters. The sanitizers are applied exactly in the order
157 that is configured. Each sanitizer works on the results of the previous one.
158
159 The following is a list of sanitizers that are shipped with Nominatim.
160
161 ##### split-name-list
162
163 ::: nominatim.tokenizer.sanitizers.split_name_list
164     selection:
165         members: False
166     rendering:
167         heading_level: 6
168
169 ##### strip-brace-terms
170
171 ::: nominatim.tokenizer.sanitizers.strip_brace_terms
172     selection:
173         members: False
174     rendering:
175         heading_level: 6
176
177 ##### tag-analyzer-by-language
178
179 ::: nominatim.tokenizer.sanitizers.tag_analyzer_by_language
180     selection:
181         members: False
182     rendering:
183         heading_level: 6
184
185
186
187 #### Token Analysis
188
189 Token analyzers take a full name and transform it into one or more normalized
190 form that are then saved in the search index. In its simplest form, the
191 analyzer only applies the transliteration rules. More complex analyzers
192 create additional spelling variants of a name. This is useful to handle
193 decomposition and abbreviation.
194
195 The ICU tokenizer may use different analyzers for different names. To select
196 the analyzer to be used, the name must be tagged with the `analyzer` attribute
197 by a sanitizer (see for example the
198 [tag-analyzer-by-language sanitizer](#tag-analyzer-by-language)).
199
200 The token-analysis section contains the list of configured analyzers. Each
201 analyzer must have an `id` parameter that uniquely identifies the analyzer.
202 The only exception is the default analyzer that is used when no special
203 analyzer was selected.
204
205 Different analyzer implementations may exist. To select the implementation,
206 the `analyzer` parameter must be set. Currently there is only one implementation
207 `generic` which is described in the following.
208
209 ##### Generic token analyzer
210
211 The generic analyzer is able to create variants from a list of given
212 abbreviation and decomposition replacements. It takes one optional parameter
213 `variants` which lists the replacements to apply. If the section is
214 omitted, then the generic analyzer becomes a simple analyzer that only
215 applies the transliteration.
216
217 The variants section defines lists of replacements which create alternative
218 spellings of a name. To create the variants, a name is scanned from left to
219 right and the longest matching replacement is applied until the end of the
220 string is reached.
221
222 The variants section must contain a list of replacement groups. Each group
223 defines a set of properties that describes where the replacements are
224 applicable. In addition, the word section defines the list of replacements
225 to be made. The basic replacement description is of the form:
226
227 ```
228 <source>[,<source>[...]] => <target>[,<target>[...]]
229 ```
230
231 The left side contains one or more `source` terms to be replaced. The right side
232 lists one or more replacements. Each source is replaced with each replacement
233 term.
234
235 !!! tip
236     The source and target terms are internally normalized using the
237     normalization rules given in the configuration. This ensures that the
238     strings match as expected. In fact, it is better to use unnormalized
239     words in the configuration because then it is possible to change the
240     rules for normalization later without having to adapt the variant rules.
241
242 ###### Decomposition
243
244 In its standard form, only full words match against the source. There
245 is a special notation to match the prefix and suffix of a word:
246
247 ``` yaml
248 - ~strasse => str  # matches "strasse" as full word and in suffix position
249 - hinter~ => hntr  # matches "hinter" as full word and in prefix position
250 ```
251
252 There is no facility to match a string in the middle of the word. The suffix
253 and prefix notation automatically trigger the decomposition mode: two variants
254 are created for each replacement, one with the replacement attached to the word
255 and one separate. So in above example, the tokenization of "hauptstrasse" will
256 create the variants "hauptstr" and "haupt str". Similarly, the name "rote strasse"
257 triggers the variants "rote str" and "rotestr". By having decomposition work
258 both ways, it is sufficient to create the variants at index time. The variant
259 rules are not applied at query time.
260
261 To avoid automatic decomposition, use the '|' notation:
262
263 ``` yaml
264 - ~strasse |=> str
265 ```
266
267 simply changes "hauptstrasse" to "hauptstr" and "rote strasse" to "rote str".
268
269 ###### Initial and final terms
270
271 It is also possible to restrict replacements to the beginning and end of a
272 name:
273
274 ``` yaml
275 - ^south => s  # matches only at the beginning of the name
276 - road$ => rd  # matches only at the end of the name
277 ```
278
279 So the first example would trigger a replacement for "south 45th street" but
280 not for "the south beach restaurant".
281
282 ###### Replacements vs. variants
283
284 The replacement syntax `source => target` works as a pure replacement. It changes
285 the name instead of creating a variant. To create an additional version, you'd
286 have to write `source => source,target`. As this is a frequent case, there is
287 a shortcut notation for it:
288
289 ```
290 <source>[,<source>[...]] -> <target>[,<target>[...]]
291 ```
292
293 The simple arrow causes an additional variant to be added. Note that
294 decomposition has an effect here on the source as well. So a rule
295
296 ``` yaml
297 - "~strasse -> str"
298 ```
299
300 means that for a word like `hauptstrasse` four variants are created:
301 `hauptstrasse`, `haupt strasse`, `hauptstr` and `haupt str`.
302
303 ### Reconfiguration
304
305 Changing the configuration after the import is currently not possible, although
306 this feature may be added at a later time.