CREATE OR REPLACE FUNCTION weigh_search(search_vector INT[],
- term_vectors TEXT[],
- weight_vectors FLOAT[],
+ rankings TEXT,
def_weight FLOAT)
RETURNS FLOAT
AS $$
DECLARE
- pos INT := 1;
- terms TEXT;
+ rank JSON;
BEGIN
- FOREACH terms IN ARRAY term_vectors
+ FOR rank IN
+ SELECT * FROM json_array_elements(rankings::JSON)
LOOP
- IF search_vector @> terms::INTEGER[] THEN
- RETURN weight_vectors[pos];
+ IF true = ALL(SELECT x::int = ANY(search_vector) FROM json_array_elements_text(rank->1) as x) THEN
+ RETURN (rank->>0)::float;
END IF;
- pos := pos + 1;
END LOOP;
RETURN def_weight;
END;
from nominatim.typing import SaFromClause, SaColumn, SaExpression
from nominatim.api.search.query import Token
+from nominatim.utils.json_writer import JsonWriter
@dataclasses.dataclass
class WeightedStrings:
"""
assert self.rankings
- return sa.func.weigh_search(table.c[self.column],
- [f"{{{','.join((str(s) for s in r.tokens))}}}"
- for r in self.rankings],
- [r.penalty for r in self.rankings],
- self.default)
+ rout = JsonWriter().start_array()
+ for rank in self.rankings:
+ rout.start_array().value(rank.penalty).next()
+ rout.start_array()
+ for token in rank.tokens:
+ rout.value(token).next()
+ rout.end_array()
+ rout.end_array().next()
+ rout.end_array()
+
+ return sa.func.weigh_search(table.c[self.column], rout(), self.default)
@dataclasses.dataclass
def end_array(self) -> 'JsonWriter':
""" Write the closing bracket of a JSON array.
"""
- assert self.pending in (',', '[', '')
- if self.pending == '[':
+ assert self.pending in (',', '[', ']', ')', '')
+ if self.pending not in (',', ''):
self.data.write(self.pending)
self.pending = ']'
return self