From: Sarah Hoffmann Date: Wed, 18 Nov 2020 07:58:38 +0000 (+0100) Subject: Merge remote-tracking branch 'upstream/master' X-Git-Tag: deploy~198 X-Git-Url: https://git.openstreetmap.org/nominatim.git/commitdiff_plain/e871fabd5ffccb9b6db16a813c3addc89683d4e6?hp=c7eb4e2c7373d64b440b3acf2186545e6a593a59 Merge remote-tracking branch 'upstream/master' --- diff --git a/.github/actions/setup-postgresql/action.yml b/.github/actions/setup-postgresql/action.yml index a5716be5..98086f2d 100644 --- a/.github/actions/setup-postgresql/action.yml +++ b/.github/actions/setup-postgresql/action.yml @@ -5,7 +5,9 @@ runs: steps: - name: Install postgis - run: sudo apt-get install -y -qq postgresql-13-postgis-3 postgresql-13-postgis-3-scripts postgresql-server-dev-13 + run: | + sudo apt-get update -qq + sudo apt-get install -y -qq postgresql-13-postgis-3 postgresql-13-postgis-3-scripts postgresql-server-dev-13 shell: bash - name: Adapt postgresql configuration diff --git a/nominatim/nominatim.py b/nominatim/nominatim.py index 0819bb11..b20673d2 100755 --- a/nominatim/nominatim.py +++ b/nominatim/nominatim.py @@ -135,19 +135,19 @@ class Indexer(object): for rank in range(max(1, self.minrank), self.maxrank): self.index(RankRunner(rank)) - if self.maxrank == 30: self.index(RankRunner(0)) self.index(InterpolationRunner(), 20) - - self.index(RankRunner(self.maxrank), 20) + self.index(RankRunner(self.maxrank), 20) + else: + self.index(RankRunner(self.maxrank)) def index(self, obj, batch=1): """ Index a single rank or table. `obj` describes the SQL to use for indexing. `batch` describes the number of objects that should be processed with a single SQL statement """ - log.warning("Starting {}".format(obj.name())) + log.warning("Starting %s (using batch size %s)", obj.name(), batch) cur = self.conn.cursor() cur.execute(obj.sql_count_objects()) diff --git a/sql/functions/address_lookup.sql b/sql/functions/address_lookup.sql index 381b7125..de6fe1d1 100644 --- a/sql/functions/address_lookup.sql +++ b/sql/functions/address_lookup.sql @@ -90,7 +90,7 @@ DECLARE for_place_id BIGINT; result TEXT[]; search TEXT[]; - found INTEGER; + current_rank_address INTEGER; location RECORD; countrylocation RECORD; searchcountrycode varchar(2); @@ -103,7 +103,7 @@ DECLARE search_unlisted_place TEXT; countryname HSTORE; BEGIN - -- The place ein question might not have a direct entry in place_addressline. + -- The place in question might not have a direct entry in place_addressline. -- Look for the parent of such places then and save if in for_place_id. postcode_isexact := false; @@ -177,9 +177,8 @@ BEGIN --RAISE WARNING '% % % %',searchcountrycode, searchhousenumber, searchpostcode; - found := 1000; -- the lowest rank_address included + -- --- Return the record for the base entry. - -- Return the record for the base entry. FOR location IN SELECT placex.place_id, osm_type, osm_id, name, coalesce(extratags->'linked_place', extratags->'place') as place_type, @@ -206,9 +205,12 @@ BEGIN location.admin_level, true, location.isaddress, location.rank_address, location.distance)::addressline; RETURN NEXT countrylocation; - found := location.rank_address; + + current_rank_address := location.rank_address; END LOOP; + -- --- Return records for address parts. + FOR location IN SELECT placex.place_id, osm_type, osm_id, name, class, type, coalesce(extratags->'linked_place', extratags->'place') as place_type, @@ -216,14 +218,15 @@ BEGIN CASE WHEN rank_address = 11 THEN 5 ELSE rank_address END as rank_address, distance, country_code, postcode FROM place_addressline join placex on (address_place_id = placex.place_id) - WHERE place_addressline.place_id = for_place_id + WHERE place_addressline.place_id IN (for_place_id, in_place_id) AND linked_place_id is null AND (placex.country_code IS NULL OR searchcountrycode IS NULL OR placex.country_code = searchcountrycode) - ORDER BY rank_address desc, isaddress desc, fromarea desc, + ORDER BY rank_address desc, (place_addressline.place_id = in_place_id) desc, + isaddress desc, fromarea desc, distance asc, rank_search desc LOOP ---RAISE WARNING '%',location; + -- RAISE WARNING '%',location; IF searchcountrycode IS NULL AND location.country_code IS NOT NULL THEN searchcountrycode := location.country_code; END IF; @@ -243,17 +246,21 @@ BEGIN location.name, location.class, location.type, location.place_type, location.admin_level, location.fromarea, - location.isaddress, location.rank_address, + location.isaddress and location.rank_address != current_rank_address, + location.rank_address, location.distance)::addressline; RETURN NEXT countrylocation; - found := location.rank_address; + + IF location.isaddress THEN + current_rank_address := location.rank_address; + END IF; END LOOP; -- If no country was included yet, add the name information from country_name. - IF found > 4 THEN + IF current_rank_address > 4 THEN SELECT name FROM country_name WHERE country_code = searchcountrycode LIMIT 1 INTO countryname; ---RAISE WARNING '% % %',found,searchcountrycode,countryname; +--RAISE WARNING '% % %',current_rank_address,searchcountrycode,countryname; IF countryname IS NOT NULL THEN location := ROW(null, null, null, countryname, 'place', 'country', NULL, null, true, true, 4, 0)::addressline; diff --git a/sql/functions/normalization.sql b/sql/functions/normalization.sql index 71b14ee5..4aea0e9b 100644 --- a/sql/functions/normalization.sql +++ b/sql/functions/normalization.sql @@ -207,19 +207,31 @@ CREATE OR REPLACE FUNCTION addr_ids_from_name(lookup_word TEXT) RETURNS INTEGER[] AS $$ DECLARE - lookup_token TEXT; + words TEXT[]; id INTEGER; return_word_id INTEGER[]; + word_ids INTEGER[]; + j INTEGER; BEGIN - lookup_token := make_standard_name(lookup_word); - SELECT array_agg(word_id) FROM word - WHERE word_token = lookup_token and class is null and type is null - INTO return_word_id; - IF return_word_id IS NULL THEN - id := nextval('seq_word'); - INSERT INTO word VALUES (id, lookup_token, null, null, null, null, 0); - return_word_id = ARRAY[id]; + words := string_to_array(make_standard_name(lookup_word), ' '); + IF array_upper(words, 1) IS NOT NULL THEN + FOR j IN 1..array_upper(words, 1) LOOP + IF (words[j] != '') THEN + SELECT array_agg(word_id) INTO word_ids + FROM word + WHERE word_token = words[j] and class is null and type is null; + + IF word_ids IS NULL THEN + id := nextval('seq_word'); + INSERT INTO word VALUES (id, words[j], null, null, null, null, 0); + return_word_id := return_word_id || id; + ELSE + return_word_id := array_merge(return_word_id, word_ids); + END IF; + END IF; + END LOOP; END IF; + RETURN return_word_id; END; $$ @@ -414,10 +426,14 @@ $$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION create_poi_search_terms(parent_place_id BIGINT, +CREATE OR REPLACE FUNCTION create_poi_search_terms(obj_place_id BIGINT, + in_partition SMALLINT, + parent_place_id BIGINT, address HSTORE, + country TEXT, housenumber TEXT, initial_name_vector INTEGER[], + geometry GEOMETRY, OUT name_vector INTEGER[], OUT nameaddress_vector INTEGER[]) AS $$ @@ -427,34 +443,60 @@ DECLARE addr_place_ids INTEGER[]; addr_item RECORD; + parent_address_place_ids BIGINT[]; + filtered_address HSTORE; BEGIN - -- Compute all search terms from the addr: tags. nameaddress_vector := '{}'::INTEGER[]; - IF address IS NOT NULL THEN - FOR addr_item IN SELECT * FROM each(address) + SELECT s.name_vector, s.nameaddress_vector + INTO parent_name_vector, parent_address_vector + FROM search_name s + WHERE s.place_id = parent_place_id; + + -- Find all address tags that don't appear in the parent search names. + SELECT hstore(array_agg(ARRAY[k, v])) INTO filtered_address + FROM (SELECT skeys(address) as k, svals(address) as v) a + WHERE not addr_ids_from_name(v) && parent_address_vector + AND k not in ('country', 'street', 'place', 'postcode', + 'housenumber', 'streetnumber', 'conscriptionnumber'); + + -- Compute all search terms from the addr: tags. + IF filtered_address IS NOT NULL THEN + FOR addr_item IN + SELECT * FROM + get_places_for_addr_tags(in_partition, geometry, filtered_address, country) LOOP - IF addr_item.key IN ('city', 'tiger:county', 'state', 'suburb', 'province', - 'district', 'region', 'county', 'municipality', - 'hamlet', 'village', 'subdistrict', 'town', - 'neighbourhood', 'quarter', 'parish') - THEN - nameaddress_vector := array_merge(nameaddress_vector, - addr_ids_from_name(addr_item.value)); - END IF; + IF addr_item.place_id is null THEN + nameaddress_vector := array_merge(nameaddress_vector, + addr_item.keywords); + CONTINUE; + END IF; + + IF parent_address_place_ids is null THEN + SELECT array_agg(parent_place_id) INTO parent_address_place_ids + FROM place_addressline + WHERE place_id = parent_place_id; + END IF; + + IF not parent_address_place_ids @> ARRAY[addr_item.place_id] THEN + nameaddress_vector := array_merge(nameaddress_vector, + addr_item.keywords); + + INSERT INTO place_addressline (place_id, address_place_id, fromarea, + isaddress, distance, cached_rank_address) + VALUES (obj_place_id, addr_item.place_id, not addr_item.isguess, + true, addr_item.distance, addr_item.rank_address); + END IF; END LOOP; END IF; + -- If the POI is named, simply mix in all address terms and be done. IF array_length(initial_name_vector, 1) is not NULL THEN -- Cheating here by not recomputing all terms but simply using the ones -- from the parent object. - SELECT array_merge(s.name_vector, s.nameaddress_vector) - INTO parent_address_vector - FROM search_name s - WHERE s.place_id = parent_place_id; - name_vector := initial_name_vector; + nameaddress_vector := array_merge(nameaddress_vector, parent_name_vector); nameaddress_vector := array_merge(nameaddress_vector, parent_address_vector); IF not address ? 'street' and address ? 'place' THEN @@ -475,11 +517,6 @@ BEGIN RETURN; END IF; - SELECT s.name_vector, s.nameaddress_vector - INTO parent_name_vector, parent_address_vector - FROM search_name s - WHERE s.place_id = parent_place_id; - -- Check if the parent covers all address terms. -- If not, create a search name entry with the house number as the name. -- This is unusual for the search_name table but prevents that the place @@ -493,16 +530,14 @@ BEGIN addr_place_ids := addr_ids_from_name(address->'place'); IF not addr_place_ids <@ parent_name_vector THEN -- addr:place tag exists without a corresponding place. Mix in addr:place - -- in the address and drop the name from the parent. This would only be - -- the street name of the nearest street. - nameaddress_vector := array_merge(nameaddress_vector, addr_place_ids); + -- in the address. name_vector := ARRAY[getorcreate_name_id(housenumber)]; + nameaddress_vector := array_merge(nameaddress_vector, addr_place_ids); END IF; - ELSE - nameaddress_vector := array_merge(nameaddress_vector, parent_name_vector); END IF; - -- The address vector always gets merged in. + -- Merge the parent name and address. + nameaddress_vector := array_merge(nameaddress_vector, parent_name_vector); nameaddress_vector := array_merge(nameaddress_vector, parent_address_vector); END; diff --git a/sql/functions/placex_triggers.sql b/sql/functions/placex_triggers.sql index 6848140a..7d6352b4 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; @@ -254,6 +255,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 +267,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 @@ -808,13 +814,17 @@ BEGIN END IF; - IF NOT %REVERSE-ONLY% THEN + IF 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 + IF not %REVERSE-ONLY% AND array_length(name_vector, 1) is not NULL THEN INSERT INTO search_name (place_id, search_rank, address_rank, importance, country_code, name_vector, nameaddress_vector, centroid) @@ -920,7 +930,8 @@ BEGIN NEW.address, CASE WHEN (NEW.rank_address = 0 or NEW.rank_search between 26 and 29) - THEN NEW.geometry ELSE NEW.centroid END) + THEN NEW.geometry ELSE NEW.centroid END, + 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; diff --git a/sql/functions/ranking.sql b/sql/functions/ranking.sql index a84269fe..51dcd0d0 100644 --- a/sql/functions/ranking.sql +++ b/sql/functions/ranking.sql @@ -233,3 +233,50 @@ BEGIN END; $$ LANGUAGE plpgsql IMMUTABLE; + +CREATE OR REPLACE FUNCTION get_addr_tag_rank(key TEXT, country TEXT, + OUT from_rank SMALLINT, + OUT to_rank SMALLINT, + OUT extent FLOAT) + AS $$ +DECLARE + ranks RECORD; +BEGIN + from_rank := null; + + FOR ranks IN + SELECT * FROM + (SELECT l.rank_search, l.rank_address FROM address_levels l + WHERE (l.country_code = country or l.country_code is NULL) + AND l.class = 'place' AND l.type = key + ORDER BY l.country_code LIMIT 1) r + WHERE rank_address > 0 + LOOP + extent := reverse_place_diameter(ranks.rank_search); + + IF ranks.rank_address <= 4 THEN + from_rank := 4; + to_rank := 4; + ELSEIF ranks.rank_address <= 9 THEN + from_rank := 5; + to_rank := 9; + ELSEIF ranks.rank_address <= 12 THEN + from_rank := 10; + to_rank := 12; + ELSEIF ranks.rank_address <= 16 THEN + from_rank := 13; + to_rank := 16; + ELSEIF ranks.rank_address <= 21 THEN + from_rank := 17; + to_rank := 21; + ELSEIF ranks.rank_address <= 24 THEN + from_rank := 22; + to_rank := 24; + ELSE + from_rank := 25; + to_rank := 25; + END IF; + END LOOP; +END; +$$ +LANGUAGE plpgsql IMMUTABLE; diff --git a/sql/partition-functions.src.sql b/sql/partition-functions.src.sql index 97520f99..1197b3b7 100644 --- a/sql/partition-functions.src.sql +++ b/sql/partition-functions.src.sql @@ -10,8 +10,8 @@ CREATE TYPE nearfeaturecentr AS ( centroid GEOMETRY ); - -- feature intersects geoemtry - -- for areas and linestrings they must touch at least along a line +-- feature intersects geoemtry +-- for areas and linestrings they must touch at least along a line CREATE OR REPLACE FUNCTION is_relevant_geometry(de9im TEXT, geom_type TEXT) RETURNS BOOLEAN AS $$ @@ -39,8 +39,10 @@ BEGIN -- start IF in_partition = -partition- THEN - FOR r IN - SELECT place_id, keywords, rank_address, rank_search, min(ST_Distance(feature, centroid)) as distance, isguess, postcode, centroid + FOR r IN + SELECT place_id, keywords, rank_address, rank_search, + min(ST_Distance(feature, centroid)) as distance, + isguess, postcode, centroid FROM location_area_large_-partition- WHERE geometry && feature AND is_relevant_geometry(ST_Relate(geometry, feature), ST_GeometryType(feature)) @@ -58,6 +60,54 @@ END $$ LANGUAGE plpgsql STABLE; +CREATE OR REPLACE FUNCTION get_places_for_addr_tags(in_partition SMALLINT, + feature GEOMETRY, + address HSTORE, country TEXT) + RETURNS SETOF nearfeaturecentr + AS $$ +DECLARE + r nearfeaturecentr%rowtype; + item RECORD; +BEGIN + FOR item IN + SELECT (get_addr_tag_rank(key, country)).*, key, name FROM + (SELECT skeys(address) as key, svals(address) as name) x + LOOP + IF item.from_rank is null THEN + CONTINUE; + END IF; + +-- start + IF in_partition = -partition- THEN + SELECT place_id, keywords, rank_address, rank_search, + min(ST_Distance(feature, centroid)) as distance, + isguess, postcode, centroid INTO r + FROM location_area_large_-partition- + WHERE geometry && ST_Expand(feature, item.extent) + AND rank_address between item.from_rank and item.to_rank + AND word_ids_from_name(item.name) && keywords + GROUP BY place_id, keywords, rank_address, rank_search, isguess, postcode, centroid + ORDER BY bool_or(ST_Intersects(geometry, feature)), distance LIMIT 1; + IF r.place_id is null THEN + -- If we cannot find a place for the term, just return the + -- search term for the given name. That ensures that the address + -- element can still be searched for, even though it will not be + -- displayed. + RETURN NEXT ROW(null, addr_ids_from_name(item.name), null, null, + null, null, null, null)::nearfeaturecentr; + ELSE + RETURN NEXT r; + END IF; + CONTINUE; + END IF; +-- end + + RAISE EXCEPTION 'Unknown partition %', in_partition; + END LOOP; +END; +$$ +LANGUAGE plpgsql STABLE; + create or replace function deleteLocationArea(in_partition INTEGER, in_place_id BIGINT, in_rank_search INTEGER) RETURNS BOOLEAN AS $$ DECLARE BEGIN @@ -126,7 +176,7 @@ BEGIN INTO parent WHERE name_vector && isin_token AND centroid && ST_Expand(point, 0.015) - AND search_rank between 26 and 27 + AND address_rank between 26 and 27 ORDER BY ST_Distance(centroid, point) ASC limit 1; RETURN parent; END IF; @@ -153,7 +203,7 @@ BEGIN FROM search_name_-partition- WHERE name_vector && isin_token AND centroid && ST_Expand(point, 0.04) - AND search_rank between 16 and 25 + AND address_rank between 16 and 25 ORDER BY ST_Distance(centroid, point) ASC limit 1; RETURN parent; END IF; @@ -164,7 +214,6 @@ END $$ LANGUAGE plpgsql STABLE; - create or replace function insertSearchName( in_partition INTEGER, in_place_id BIGINT, in_name_vector INTEGER[], in_rank_search INTEGER, in_rank_address INTEGER, in_geometry GEOMETRY) @@ -175,8 +224,8 @@ BEGIN IF in_partition = -partition- THEN DELETE FROM search_name_-partition- values WHERE place_id = in_place_id; IF in_rank_address > 0 THEN - INSERT INTO search_name_-partition- (place_id, search_rank, address_rank, name_vector, centroid) - values (in_place_id, in_rank_search, in_rank_address, in_name_vector, in_geometry); + INSERT INTO search_name_-partition- (place_id, address_rank, name_vector, centroid) + values (in_place_id, in_rank_address, in_name_vector, in_geometry); END IF; RETURN TRUE; END IF; diff --git a/sql/partition-tables.src.sql b/sql/partition-tables.src.sql index 8749243e..df2cac70 100644 --- a/sql/partition-tables.src.sql +++ b/sql/partition-tables.src.sql @@ -1,7 +1,6 @@ drop table IF EXISTS search_name_blank CASCADE; CREATE TABLE search_name_blank ( place_id BIGINT, - search_rank smallint, address_rank smallint, name_vector integer[], centroid GEOMETRY(Geometry, 4326) @@ -15,8 +14,8 @@ CREATE INDEX idx_location_area_large_-partition-_geometry ON location_area_large CREATE TABLE search_name_-partition- () INHERITS (search_name_blank) {ts:address-data}; CREATE INDEX idx_search_name_-partition-_place_id ON search_name_-partition- USING BTREE (place_id) {ts:address-index}; -CREATE INDEX idx_search_name_-partition-_centroid_street ON search_name_-partition- USING GIST (centroid) {ts:address-index} where search_rank between 26 and 27; -CREATE INDEX idx_search_name_-partition-_centroid_place ON search_name_-partition- USING GIST (centroid) {ts:address-index} where search_rank between 2 and 25; +CREATE INDEX idx_search_name_-partition-_centroid_street ON search_name_-partition- USING GIST (centroid) {ts:address-index} where address_rank between 26 and 27; +CREATE INDEX idx_search_name_-partition-_centroid_place ON search_name_-partition- USING GIST (centroid) {ts:address-index} where address_rank between 2 and 25; DROP TABLE IF EXISTS location_road_-partition-; CREATE TABLE location_road_-partition- ( diff --git a/test/bdd/db/import/addressing.feature b/test/bdd/db/import/addressing.feature index 52f966d8..9050c19b 100644 --- a/test/bdd/db/import/addressing.feature +++ b/test/bdd/db/import/addressing.feature @@ -298,3 +298,102 @@ Feature: Address computation | object | address | | W1 | W2 | + Scenario: addr:* tags are honored even when a street is far away from the place + Given the grid + | 1 | | 2 | | | 5 | + | | | | 8 | 9 | | + | 4 | | 3 | | | 6 | + And the places + | osm | class | type | admin | name | geometry | + | R1 | boundary | administrative | 8 | Left | (1,2,3,4,1) | + | R2 | boundary | administrative | 8 | Right | (2,3,6,5,2) | + And the places + | osm | class | type | addr+city | geometry | + | W1 | highway | primary | Left | 8,9 | + | W2 | highway | primary | Right | 8,9 | + When importing + Then place_addressline contains + | object | address | isaddress | + | W1 | R1 | True | + | W1 | R2 | False | + | W2 | R2 | True | + And place_addressline doesn't contain + | object | address | + | W2 | R1 | + + + Scenario: addr:* tags are honored even when a POI is far away from the place + Given the grid + | 1 | | 2 | | | 5 | + | | | | 8 | 9 | | + | 4 | | 3 | | | 6 | + And the places + | osm | class | type | admin | name | geometry | + | R1 | boundary | administrative | 8 | Left | (1,2,3,4,1) | + | R2 | boundary | administrative | 8 | Right | (2,3,6,5,2) | + And the places + | osm | class | type | name | addr+city | geometry | + | W1 | highway | primary | Wonderway | Right | 8,9 | + | N1 | amenity | cafe | Bolder | Left | 9 | + When importing + Then place_addressline contains + | object | address | isaddress | + | W1 | R2 | True | + | N1 | R1 | True | + And place_addressline doesn't contain + | object | address | + | W1 | R1 | + When searching for "Bolder" + Then results contain + | osm_type | osm_id | name | + | N | 1 | Bolder, Wonderway, Left | + + Scenario: addr:* tags do not produce addresslines when the parent has the address part + Given the grid + | 1 | | | 5 | + | | 8 | 9 | | + | 4 | | | 6 | + And the places + | osm | class | type | admin | name | geometry | + | R1 | boundary | administrative | 8 | Outer | (1,5,6,4,1) | + And the places + | osm | class | type | name | addr+city | geometry | + | W1 | highway | primary | Wonderway | Outer | 8,9 | + | N1 | amenity | cafe | Bolder | Outer | 9 | + When importing + Then place_addressline contains + | object | address | isaddress | + | W1 | R1 | True | + And place_addressline doesn't contain + | object | address | + | N1 | R1 | + When searching for "Bolder" + Then results contain + | osm_type | osm_id | name | + | N | 1 | Bolder, Wonderway, Outer | + + Scenario: addr:* tags on outside do not produce addresslines when the parent has the address part + Given the grid + | 1 | | 2 | | | 5 | + | | | | 8 | 9 | | + | 4 | | 3 | | | 6 | + And the places + | osm | class | type | admin | name | geometry | + | R1 | boundary | administrative | 8 | Left | (1,2,3,4,1) | + | R2 | boundary | administrative | 8 | Right | (2,3,6,5,2) | + And the places + | osm | class | type | name | addr+city | geometry | + | W1 | highway | primary | Wonderway | Left | 8,9 | + | N1 | amenity | cafe | Bolder | Left | 9 | + When importing + Then place_addressline contains + | object | address | isaddress | + | W1 | R1 | True | + | W1 | R2 | False | + And place_addressline doesn't contain + | object | address | + | N1 | R1 | + When searching for "Bolder" + Then results contain + | osm_type | osm_id | name | + | N | 1 | Bolder, Wonderway, Left | diff --git a/test/bdd/db/import/linking.feature b/test/bdd/db/import/linking.feature index fa96e5b3..1e0d131a 100644 --- a/test/bdd/db/import/linking.feature +++ b/test/bdd/db/import/linking.feature @@ -14,7 +14,22 @@ Feature: Linking of places | R13 | - | | N256 | - | - Scenario: Waterways are linked when in waterway relations + Scenario: Postcode areas cannot be linked + Given the grid + | 1 | | 2 | + | | 9 | | + | 4 | | 3 | + And the named places + | osm | class | type | addr+postcode | extra+wikidata | geometry | + | R13 | boundary | postal_code | 123 | Q87493 | (1,2,3,4,1) | + | N25 | place | suburb | 123 | Q87493 | 9 | + When importing + Then placex contains + | object | linked_place_id | + | R13 | - | + | N25 | - | + + Scenario: Waterways are linked when in waterway relations Given the scene split-road And the places | osm | class | type | name | geometry | diff --git a/test/bdd/db/import/search_name.feature b/test/bdd/db/import/search_name.feature index a0a53911..30c430a6 100644 --- a/test/bdd/db/import/search_name.feature +++ b/test/bdd/db/import/search_name.feature @@ -30,7 +30,24 @@ Feature: Creation of search terms | osm_type | osm_id | name | | N | 1 | 23, Rose Street | - Scenario: Unnamed POI has no search entry when it has known addr: tags + Scenario: Searching for unknown addr: tags also works for multiple words + Given the scene roads-with-pois + And the places + | osm | class | type | housenr | addr+city | geometry | + | N1 | place | house | 23 | Little Big Town | :p-N1 | + And the places + | osm | class | type | name+name | geometry | + | W1 | highway | residential | Rose Street | :w-north | + When importing + Then search_name contains + | object | name_vector | nameaddress_vector | + | N1 | #23 | Rose Street, Little, Big, Town | + When searching for "23 Rose Street, Little Big Town" + Then results contain + | osm_type | osm_id | name | + | N | 1 | 23, Rose Street | + + Scenario: Unnamed POI has no search entry when it has known addr: tags Given the scene roads-with-pois And the places | osm | class | type | housenr | addr+city | geometry | @@ -56,7 +73,7 @@ Feature: Creation of search terms When importing Then search_name has no entry for N1 - Scenario: Unnamed POIs doesn't inherit parent name when unknown addr:place is present + Scenario: Unnamed POIs inherit parent name when unknown addr:place is present Given the scene roads-with-pois And the places | osm | class | type | housenr | addr+place | geometry | @@ -66,15 +83,18 @@ Feature: Creation of search terms | W1 | highway | residential | Rose Street | :w-north | | N2 | place | city | Strange Town | :p-N1 | When importing + Then placex contains + | object | parent_place_id | + | N1 | N2 | Then search_name contains | object | name_vector | nameaddress_vector | - | N1 | #23 | Walltown | + | N1 | #23 | Walltown, Strange, Town | When searching for "23 Rose Street" Then exactly 1 results are returned And results contain | osm_type | osm_id | name | | W | 1 | Rose Street, Strange Town | - When searching for "23 Walltown" + When searching for "23 Walltown, Strange Town" Then results contain | osm_type | osm_id | name | | N | 1 | 23, Walltown, Strange Town | @@ -185,20 +205,19 @@ Feature: Creation of search terms | object | name_vector | nameaddress_vector | | N1 | foo | the road | - Scenario: Some addr: tags are added to address when the name exists + Scenario: Some addr: tags are added to address Given the scene roads-with-pois And the places | osm | class | type | name | geometry | - | N1 | place | state | new york | 80 80 | | N2 | place | city | bonn | 81 81 | | N3 | place | suburb | smalltown| 80 81 | And the named places - | osm | class | type | addr+city | addr+state | addr+suburb | geometry | - | W1 | highway | service | bonn | New York | Smalltown | :w-north | + | osm | class | type | addr+city | addr+municipality | addr+suburb | geometry | + | W1 | highway | service | bonn | New York | Smalltown | :w-north | When importing Then search_name contains | object | nameaddress_vector | - | W1 | bonn, new york, smalltown | + | W1 | bonn, new, york, smalltown | Scenario: A known addr:* tag is added even if the name is unknown Given the scene roads-with-pois