X-Git-Url: https://git.openstreetmap.org/nominatim.git/blobdiff_plain/928c6245c9b08abeeaf4af3fe105eee1ada4bac9..987d60ccdaa750defcd09ce64f19e3e049222802:/sql/functions/placex_triggers.sql diff --git a/sql/functions/placex_triggers.sql b/sql/functions/placex_triggers.sql index 6848140a..ea9474e4 100644 --- a/sql/functions/placex_triggers.sql +++ b/sql/functions/placex_triggers.sql @@ -138,6 +138,7 @@ DECLARE BEGIN IF bnd.rank_search >= 26 or bnd.rank_address = 0 or ST_GeometryType(bnd.geometry) NOT IN ('ST_Polygon','ST_MultiPolygon') + or bnd.type IN ('postcode', 'postal_code') THEN RETURN NULL; END IF; @@ -182,6 +183,7 @@ BEGIN WHERE make_standard_name(name->'name') = bnd_name AND placex.class = 'place' AND placex.type = bnd.extratags->'place' AND placex.osm_type = 'N' + AND placex.linked_place_id is null AND placex.rank_search < 26 -- needed to select the right index AND _st_covers(bnd.geometry, placex.geometry) LOOP @@ -196,6 +198,7 @@ BEGIN WHERE placex.class = 'place' AND placex.osm_type = 'N' AND placex.extratags ? 'wikidata' -- needed to select right index AND placex.extratags->'wikidata' = bnd.extratags->'wikidata' + AND placex.linked_place_id is null AND placex.rank_search < 26 AND _st_covers(bnd.geometry, placex.geometry) ORDER BY make_standard_name(name->'name') = bnd_name desc @@ -218,6 +221,7 @@ BEGIN false, placex.postcode)).address_rank) OR (bnd.rank_address = 0 and placex.rank_search = bnd.rank_search)) AND placex.osm_type = 'N' + AND placex.linked_place_id is null AND placex.rank_search < 26 -- needed to select the right index AND _st_covers(bnd.geometry, placex.geometry) LOOP @@ -254,6 +258,7 @@ CREATE OR REPLACE FUNCTION insert_addresslines(obj_place_id BIGINT, maxrank SMALLINT, address HSTORE, geometry GEOMETRY, + country TEXT, OUT parent_place_id BIGINT, OUT postcode TEXT, OUT nameaddress_vector INT[]) @@ -265,45 +270,49 @@ DECLARE current_boundary GEOMETRY := NULL; current_node_area GEOMETRY := NULL; - location RECORD; - addr_item RECORD; + parent_place_rank INT := 0; + addr_place_ids BIGINT[]; - isin_tokens INT[]; + location RECORD; BEGIN parent_place_id := 0; nameaddress_vector := '{}'::int[]; - isin_tokens := '{}'::int[]; - ---- convert address store to array of tokenids - IF address IS NOT NULL THEN - FOR addr_item IN SELECT * FROM each(address) - LOOP - IF addr_item.key IN ('city', 'tiger:county', 'state', 'suburb', 'province', - 'district', 'region', 'county', 'municipality', - 'hamlet', 'village', 'subdistrict', 'town', - 'neighbourhood', 'quarter', 'parish') - THEN - isin_tokens := array_merge(isin_tokens, - word_ids_from_name(addr_item.value)); - IF NOT %REVERSE-ONLY% THEN - nameaddress_vector := array_merge(nameaddress_vector, - addr_ids_from_name(addr_item.value)); + address_havelevel := array_fill(false, ARRAY[maxrank]); + + FOR location IN + SELECT * FROM get_places_for_addr_tags(partition, geometry, + address, country) + ORDER BY rank_address, distance, isguess desc + LOOP + IF NOT %REVERSE-ONLY% THEN + nameaddress_vector := array_merge(nameaddress_vector, + location.keywords::int[]); + END IF; + + IF location.place_id is not null THEN + location_isaddress := not address_havelevel[location.rank_address]; + IF not address_havelevel[location.rank_address] THEN + address_havelevel[location.rank_address] := true; + IF parent_place_rank < location.rank_address THEN + parent_place_id := location.place_id; + parent_place_rank := location.rank_address; END IF; END IF; - END LOOP; - END IF; - IF NOT %REVERSE-ONLY% THEN - nameaddress_vector := array_merge(nameaddress_vector, isin_tokens); - END IF; - ---- now compute the address terms - FOR i IN 1..maxrank LOOP - address_havelevel[i] := false; + INSERT INTO place_addressline (place_id, address_place_id, fromarea, + isaddress, distance, cached_rank_address) + VALUES (obj_place_id, location.place_id, not location.isguess, + true, location.distance, location.rank_address); + + addr_place_ids := array_append(addr_place_ids, location.place_id); + END IF; END LOOP; FOR location IN SELECT * FROM getNearFeatures(partition, geometry, maxrank) - ORDER BY rank_address, isin_tokens && keywords desc, isguess asc, + WHERE addr_place_ids is null or not addr_place_ids @> ARRAY[place_id] + ORDER BY rank_address, isguess asc, distance * CASE WHEN rank_address = 16 AND rank_search = 15 THEN 0.2 WHEN rank_address = 16 AND rank_search = 16 THEN 0.25 @@ -502,7 +511,7 @@ DECLARE location RECORD; relation_members TEXT[]; - centroid GEOMETRY; + geom GEOMETRY; parent_address_level SMALLINT; place_address_level SMALLINT; @@ -808,11 +817,15 @@ BEGIN END IF; - IF NOT %REVERSE-ONLY% THEN + IF not %REVERSE-ONLY% AND (array_length(name_vector, 1) is not NULL + OR inherited_address is not NULL OR NEW.address is not NULL) + THEN SELECT * INTO name_vector, nameaddress_vector - FROM create_poi_search_terms(NEW.parent_place_id, + FROM create_poi_search_terms(NEW.place_id, + NEW.partition, NEW.parent_place_id, inherited_address || NEW.address, - NEW.housenumber, name_vector); + NEW.country_code, NEW.housenumber, + name_vector, NEW.centroid); IF array_length(name_vector, 1) is not NULL THEN INSERT INTO search_name (place_id, search_rank, address_rank, @@ -839,9 +852,9 @@ BEGIN -- Use the linked point as the centre point of the geometry, -- but only if it is within the area of the boundary. - centroid := coalesce(location.centroid, ST_Centroid(location.geometry)); - IF centroid is not NULL AND ST_Within(centroid, NEW.geometry) THEN - NEW.centroid := centroid; + geom := coalesce(location.centroid, ST_Centroid(location.geometry)); + IF geom is not NULL AND ST_Within(geom, NEW.geometry) THEN + NEW.centroid := geom; END IF; --DEBUG: RAISE WARNING 'parent address: % rank address: %', parent_address_level, location.rank_address; @@ -908,8 +921,23 @@ BEGIN --DEBUG: RAISE WARNING 'Country names updated'; END IF; + -- For linear features we need the full geometry for determining the address + -- because they may go through several administrative entities. Otherwise use + -- the centroid for performance reasons. + IF ST_GeometryType(NEW.geometry) in ('ST_LineString', 'ST_MultiLineString') THEN + geom := NEW.geometry; + ELSE + geom := NEW.centroid; + END IF; + IF NEW.rank_address = 0 THEN max_rank := geometry_to_rank(NEW.rank_search, NEW.geometry, NEW.country_code); + -- Rank 0 features may also span multiple administrative areas (e.g. lakes) + -- so use the geometry here too. Just make sure the areas don't become too + -- large. + IF NEW.class = 'natural' or max_rank > 10 THEN + geom := NEW.geometry; + END IF; ELSEIF NEW.rank_address > 25 THEN max_rank := 25; ELSE @@ -917,10 +945,7 @@ BEGIN END IF; SELECT * FROM insert_addresslines(NEW.place_id, NEW.partition, max_rank, - NEW.address, - CASE WHEN (NEW.rank_address = 0 or - NEW.rank_search between 26 and 29) - THEN NEW.geometry ELSE NEW.centroid END) + NEW.address, geom, NEW.country_code) INTO NEW.parent_place_id, NEW.postcode, nameaddress_vector; --DEBUG: RAISE WARNING 'RETURN insert_addresslines: %, %, %', NEW.parent_place_id, NEW.postcode, nameaddress_vector;