]> git.openstreetmap.org Git - nominatim.git/blob - docs/develop/ICU-Tokenizer-Modules.md
Drop the place_classtype tables on migration
[nominatim.git] / docs / develop / ICU-Tokenizer-Modules.md
1 # Writing custom token analysis modules for the ICU tokenizer
2
3 The [ICU tokenizer](../customize/Tokenizers.md#icu-tokenizer) provides a
4 highly customizable method to pre-process and normalize the name information
5 of the input data before it is added to the search index. It comes with a
6 selection of token analyzers which you can use to adapt your
7 installation to your needs. If the provided modules are not enough, you can
8 also provide your own implementations. This section describes the API
9 for token analysis.
10
11 !!! warning
12     This API is currently in early alpha status. While this API is meant to
13     be a public API on which other token analyzers may be
14     implemented, it is not guaranteed to be stable at the moment.
15
16
17 ## Using custom token analysis modules
18
19 Token analysis names as set in the `analyzer` property
20 may refer to externally supplied modules. There are two ways
21 to include external modules: through a library or from the project directory.
22
23 To include a module from a library, use the absolute import path as name and
24 make sure the library can be found in your PYTHONPATH.
25
26 To use a custom module without creating a library, you can put the module
27 somewhere in your project directory and then use the relative path to the
28 file. Include the whole name of the file including the `.py` ending.
29
30
31 ## Custom token analysis module
32
33 ::: nominatim_db.tokenizer.token_analysis.base.AnalysisModule
34     options:
35         heading_level: 6
36
37
38 ::: nominatim_db.tokenizer.token_analysis.base.Analyzer
39     options:
40         heading_level: 6
41
42 ### Example: Creating acronym variants for long names
43
44 The following example of a token analysis module creates acronyms from
45 very long names and adds them as a variant:
46
47 ``` python
48 class AcronymMaker:
49     """ This class is the actual analyzer.
50     """
51     def __init__(self, norm, trans):
52         self.norm = norm
53         self.trans = trans
54
55
56     def get_canonical_id(self, name):
57         # In simple cases, the normalized name can be used as a canonical id.
58         return self.norm.transliterate(name.name).strip()
59
60
61     def compute_variants(self, name):
62         # The transliterated form of the name always makes up a variant.
63         variants = [self.trans.transliterate(name)]
64
65         # Only create acronyms from very long words.
66         if len(name) > 20:
67             # Take the first letter from each word to form the acronym.
68             acronym = ''.join(w[0] for w in name.split())
69             # If that leds to an acronym with at least three letters,
70             # add the resulting acronym as a variant.
71             if len(acronym) > 2:
72                 # Never forget to transliterate the variants before returning them.
73                 variants.append(self.trans.transliterate(acronym))
74
75         return variants
76
77 # The following two functions are the module interface.
78
79 def configure(rules, normalizer, transliterator):
80     # There is no configuration to parse and no data to set up.
81     # Just return an empty configuration.
82     return None
83
84
85 def create(normalizer, transliterator, config):
86     # Return a new instance of our token analysis class above.
87     return AcronymMaker(normalizer, transliterator)
88 ```
89
90 Given the name `Trans-Siberian Railway`, the code above would return the full
91 name `Trans-Siberian Railway` and the acronym `TSR` as variant, so that
92 searching would work for both.
93
94 ## Sanitizers vs. Token analysis - what to use for variants?
95
96 It is not always clear when to implement variations in the sanitizer and
97 when to write a token analysis module. Just take the acronym example
98 above: it would also have been possible to write a sanitizer which adds the
99 acronym as an additional name to the name list. The result would have been
100 similar. So which should be used when?
101
102 The most important thing to keep in mind is that variants created by the
103 token analysis are only saved in the word lookup table. They do not need
104 extra space in the search index. If there are many spelling variations, this
105 can mean quite a significant amount of space is saved.
106
107 When creating additional names with a sanitizer, these names are completely
108 independent. In particular, they can be fed into different token analysis
109 modules. This gives a much greater flexibility but at the price that the
110 additional names increase the size of the search index.
111