]> git.openstreetmap.org Git - nominatim.git/blob - lib-sql/tokenizer/icu_tokenizer.sql
icu tokenizer: switch to matching against partial names
[nominatim.git] / lib-sql / tokenizer / icu_tokenizer.sql
1 -- Get tokens used for searching the given place.
2 --
3 -- These are the tokens that will be saved in the search_name table.
4 CREATE OR REPLACE FUNCTION token_get_name_search_tokens(info JSONB)
5   RETURNS INTEGER[]
6 AS $$
7   SELECT (info->>'names')::INTEGER[]
8 $$ LANGUAGE SQL IMMUTABLE STRICT;
9
10
11 -- Get tokens for matching the place name against others.
12 --
13 -- This should usually be restricted to full name tokens.
14 CREATE OR REPLACE FUNCTION token_get_name_match_tokens(info JSONB)
15   RETURNS INTEGER[]
16 AS $$
17   SELECT (info->>'names')::INTEGER[]
18 $$ LANGUAGE SQL IMMUTABLE STRICT;
19
20
21 -- Return the housenumber tokens applicable for the place.
22 CREATE OR REPLACE FUNCTION token_get_housenumber_search_tokens(info JSONB)
23   RETURNS INTEGER[]
24 AS $$
25   SELECT (info->>'hnr_tokens')::INTEGER[]
26 $$ LANGUAGE SQL IMMUTABLE STRICT;
27
28
29 -- Return the housenumber in the form that it can be matched during search.
30 CREATE OR REPLACE FUNCTION token_normalized_housenumber(info JSONB)
31   RETURNS TEXT
32 AS $$
33   SELECT info->>'hnr';
34 $$ LANGUAGE SQL IMMUTABLE STRICT;
35
36
37 CREATE OR REPLACE FUNCTION token_has_addr_street(info JSONB)
38   RETURNS BOOLEAN
39 AS $$
40   SELECT info->>'street' is not null;
41 $$ LANGUAGE SQL IMMUTABLE;
42
43
44 CREATE OR REPLACE FUNCTION token_has_addr_place(info JSONB)
45   RETURNS BOOLEAN
46 AS $$
47   SELECT info->>'place' is not null;
48 $$ LANGUAGE SQL IMMUTABLE;
49
50
51 CREATE OR REPLACE FUNCTION token_matches_street(info JSONB, street_tokens INTEGER[])
52   RETURNS BOOLEAN
53 AS $$
54   SELECT (info->>'street')::INTEGER[] <@ street_tokens
55 $$ LANGUAGE SQL IMMUTABLE STRICT;
56
57
58 CREATE OR REPLACE FUNCTION token_matches_place(info JSONB, place_tokens INTEGER[])
59   RETURNS BOOLEAN
60 AS $$
61   SELECT (info->>'place')::INTEGER[] <@ place_tokens
62 $$ LANGUAGE SQL IMMUTABLE STRICT;
63
64
65 CREATE OR REPLACE FUNCTION token_addr_place_search_tokens(info JSONB)
66   RETURNS INTEGER[]
67 AS $$
68   SELECT (info->>'place')::INTEGER[]
69 $$ LANGUAGE SQL IMMUTABLE STRICT;
70
71
72 CREATE OR REPLACE FUNCTION token_get_address_keys(info JSONB)
73   RETURNS SETOF TEXT
74 AS $$
75   SELECT * FROM jsonb_object_keys(info->'addr');
76 $$ LANGUAGE SQL IMMUTABLE STRICT;
77
78
79 CREATE OR REPLACE FUNCTION token_get_address_search_tokens(info JSONB, key TEXT)
80   RETURNS INTEGER[]
81 AS $$
82   SELECT (info->'addr'->>key)::INTEGER[];
83 $$ LANGUAGE SQL IMMUTABLE STRICT;
84
85
86 CREATE OR REPLACE FUNCTION token_matches_address(info JSONB, key TEXT, tokens INTEGER[])
87   RETURNS BOOLEAN
88 AS $$
89   SELECT (info->'addr'->>key)::INTEGER[] <@ tokens;
90 $$ LANGUAGE SQL IMMUTABLE STRICT;
91
92
93 CREATE OR REPLACE FUNCTION token_normalized_postcode(postcode TEXT)
94   RETURNS TEXT
95 AS $$
96   SELECT CASE WHEN postcode SIMILAR TO '%(,|;)%' THEN NULL ELSE upper(trim(postcode))END;
97 $$ LANGUAGE SQL IMMUTABLE STRICT;
98
99
100 -- Return token info that should be saved permanently in the database.
101 CREATE OR REPLACE FUNCTION token_strip_info(info JSONB)
102   RETURNS JSONB
103 AS $$
104   SELECT NULL::JSONB;
105 $$ LANGUAGE SQL IMMUTABLE STRICT;
106
107 --------------- private functions ----------------------------------------------
108
109 CREATE OR REPLACE FUNCTION getorcreate_full_word(norm_term TEXT, lookup_terms TEXT[],
110                                                  OUT full_token INT,
111                                                  OUT partial_tokens INT[])
112   AS $$
113 DECLARE
114   partial_terms TEXT[] = '{}'::TEXT[];
115   term TEXT;
116   term_id INTEGER;
117   term_count INTEGER;
118 BEGIN
119   SELECT min(word_id) INTO full_token
120     FROM word WHERE word = norm_term and type = 'W';
121
122   IF full_token IS NULL THEN
123     full_token := nextval('seq_word');
124     INSERT INTO word (word_id, word_token, type, word, info)
125       SELECT full_token, lookup_term, 'W', norm_term,
126              json_build_object('count', 0)
127         FROM unnest(lookup_terms) as lookup_term;
128   END IF;
129
130   FOR term IN SELECT unnest(string_to_array(unnest(lookup_terms), ' ')) LOOP
131     term := trim(term);
132     IF NOT (ARRAY[term] <@ partial_terms) THEN
133       partial_terms := partial_terms || term;
134     END IF;
135   END LOOP;
136
137   partial_tokens := '{}'::INT[];
138   FOR term IN SELECT unnest(partial_terms) LOOP
139     SELECT min(word_id), max(info->>'count') INTO term_id, term_count
140       FROM word WHERE word_token = term and type = 'w';
141
142     IF term_id IS NULL THEN
143       term_id := nextval('seq_word');
144       term_count := 0;
145       INSERT INTO word (word_id, word_token, type, info)
146         VALUES (term_id, term, 'w', json_build_object('count', term_count));
147     END IF;
148
149     partial_tokens := array_merge(partial_tokens, ARRAY[term_id]);
150   END LOOP;
151 END;
152 $$
153 LANGUAGE plpgsql;
154
155
156 CREATE OR REPLACE FUNCTION getorcreate_partial_word(partial TEXT)
157   RETURNS INTEGER
158   AS $$
159 DECLARE
160   token INTEGER;
161 BEGIN
162   SELECT min(word_id) INTO token
163     FROM word WHERE word_token = partial and type = 'w';
164
165   IF token IS NULL THEN
166     token := nextval('seq_word');
167     INSERT INTO word (word_id, word_token, type, info)
168         VALUES (token, partial, 'w', json_build_object('count', 0));
169   END IF;
170
171   RETURN token;
172 END;
173 $$
174 LANGUAGE plpgsql;
175
176
177 CREATE OR REPLACE FUNCTION getorcreate_hnr_id(lookup_term TEXT)
178   RETURNS INTEGER
179   AS $$
180 DECLARE
181   return_id INTEGER;
182 BEGIN
183   SELECT min(word_id) INTO return_id FROM word
184     WHERE word_token = lookup_term and type = 'H';
185
186   IF return_id IS NULL THEN
187     return_id := nextval('seq_word');
188     INSERT INTO word (word_id, word_token, type)
189       VALUES (return_id, lookup_term, 'H');
190   END IF;
191
192   RETURN return_id;
193 END;
194 $$
195 LANGUAGE plpgsql;