]> git.openstreetmap.org Git - nominatim.git/blob - docs/admin/Tokenizers.md
add warning about experimental nature of 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 ### How it works
56
57 On import the tokenizer processes names in the following four stages:
58
59 1. The **Normalization** part removes all non-relevant information from the
60    input.
61 2. Incoming names are now converted to **full names**. This process is currently
62    hard coded and mostly serves to handle name tags from OSM that contain
63    multiple names (e.g. [Biel/Bienne](https://www.openstreetmap.org/node/240097197)).
64 3. Next the tokenizer creates **variants** from the full names. These variants
65    cover decomposition and abbreviation handling. Variants are saved to the
66    database, so that it is not necessary to create the variants for a search
67    query.
68 4. The final **Tokenization** step converts the names to a simple ASCII form,
69    potentially removing further spelling variants for better matching.
70
71 At query time only stage 1) and 4) are used. The query is normalized and
72 tokenized and the resulting string used for searching in the database.
73
74 ### Configuration
75
76 The ICU tokenizer is configured using a YAML file which can be configured using
77 `NOMINATIM_TOKENIZER_CONFIG`. The configuration is read on import and then
78 saved as part of the internal database status. Later changes to the variable
79 have no effect.
80
81 Here is an example configuration file:
82
83 ``` yaml
84 normalization:
85     - ":: lower ()"
86     - "ß > 'ss'" # German szet is unimbigiously equal to double ss
87 transliteration:
88     - !include /etc/nominatim/icu-rules/extended-unicode-to-asccii.yaml
89     - ":: Ascii ()"
90 variants:
91     - language: de
92       words:
93         - ~haus => haus
94         - ~strasse -> str
95     - language: en
96       words: 
97         - road -> rd
98         - bridge -> bdge,br,brdg,bri,brg
99 ```
100
101 The configuration file contains three sections:
102 `normalization`, `transliteration`, `variants`.
103
104 The normalization and transliteration sections each must contain a list of
105 [ICU transformation rules](https://unicode-org.github.io/icu/userguide/transforms/general/rules.html).
106 The rules are applied in the order in which they appear in the file.
107 You can also include additional rules from external yaml file using the
108 `!include` tag. The included file must contain a valid YAML list of ICU rules
109 and may again include other files.
110
111 !!! warning
112     The ICU rule syntax contains special characters that conflict with the
113     YAML syntax. You should therefore always enclose the ICU rules in
114     double-quotes.
115
116 The variants section defines lists of replacements which create alternative
117 spellings of a name. To create the variants, a name is scanned from left to
118 right and the longest matching replacement is applied until the end of the
119 string is reached.
120
121 The variants section must contain a list of replacement groups. Each group
122 defines a set of properties that describes where the replacements are
123 applicable. In addition, the word section defines the list of replacements
124 to be made. The basic replacement description is of the form:
125
126 ```
127 <source>[,<source>[...]] => <target>[,<target>[...]]
128 ```
129
130 The left side contains one or more `source` terms to be replaced. The right side
131 lists one or more replacements. Each source is replaced with each replacement
132 term.
133
134 !!! tip
135     The source and target terms are internally normalized using the
136     normalization rules given in the configuration. This ensures that the
137     strings match as expected. In fact, it is better to use unnormalized
138     words in the configuration because then it is possible to change the
139     rules for normalization later without having to adapt the variant rules.
140
141 #### Decomposition
142
143 In its standard form, only full words match against the source. There
144 is a special notation to match the prefix and suffix of a word:
145
146 ``` yaml
147 - ~strasse => str  # matches "strasse" as full word and in suffix position
148 - hinter~ => hntr  # matches "hinter" as full word and in prefix position
149 ```
150
151 There is no facility to match a string in the middle of the word. The suffix
152 and prefix notation automatically trigger the decomposition mode: two variants
153 are created for each replacement, one with the replacement attached to the word
154 and one separate. So in above example, the tokenization of "hauptstrasse" will
155 create the variants "hauptstr" and "haupt str". Similarly, the name "rote strasse"
156 triggers the variants "rote str" and "rotestr". By having decomposition work
157 both ways, it is sufficient to create the variants at index time. The variant
158 rules are not applied at query time.
159
160 To avoid automatic decomposition, use the '|' notation:
161
162 ``` yaml
163 - ~strasse |=> str
164 ```
165
166 simply changes "hauptstrasse" to "hauptstr" and "rote strasse" to "rote str".
167
168 #### Initial and final terms
169
170 It is also possible to restrict replacements to the beginning and end of a
171 name:
172
173 ``` yaml
174 - ^south => n  # matches only at the beginning of the name
175 - road$ => rd  # matches only at the end of the name
176 ```
177
178 So the first example would trigger a replacement for "south 45th street" but
179 not for "the south beach restaurant".
180
181 #### Replacements vs. variants
182
183 The replacement syntax `source => target` works as a pure replacement. It changes
184 the name instead of creating a variant. To create an additional version, you'd
185 have to write `source => source,target`. As this is a frequent case, there is
186 a shortcut notation for it:
187
188 ```
189 <source>[,<source>[...]] -> <target>[,<target>[...]]
190 ```
191
192 The simple arrow causes an additional variant to be added. Note that
193 decomposition has an effect here on the source as well. So a rule
194
195 ```yaml
196 - ~strasse => str
197 ```
198
199 means that for a word like `hauptstrasse` four variants are created:
200 `hauptstrasse`, `haupt strasse`, `hauptstr` and `haupt str`.
201
202 ### Reconfiguration
203
204 Changing the configuration after the import is currently not possible, although
205 this feature may be added at a later time.