]> git.openstreetmap.org Git - nominatim.git/commitdiff
for roads add all intersecting boundaries to address list
authorSarah Hoffmann <lonvia@denofr.de>
Sat, 18 Mar 2017 11:17:48 +0000 (12:17 +0100)
committerSarah Hoffmann <lonvia@denofr.de>
Sat, 18 Mar 2017 11:17:48 +0000 (12:17 +0100)
When roads cross boundaries, both administrative entities should
be added to the address list, so that both entities can be used
for searching. Also allows in a second step to better sort out
addresses of POIs on such roads.

Fixes #121.

sql/functions.sql
sql/partition-functions.src.sql
test/bdd/db/import/addressing.feature [new file with mode: 0644]
test/bdd/steps/db_ops.py

index 61228c422dd129a87fd879b7e679ef34aa56531e..be67cf011d7481c2d0d3158c1906f9db22af009c 100644 (file)
@@ -1679,7 +1679,12 @@ BEGIN
   -- added ourself as address already
   address_havelevel[NEW.rank_address] := true;
   -- RAISE WARNING '  getNearFeatures(%,''%'',%,''%'')',NEW.partition, place_centroid, search_maxrank, isin_tokens;
   -- added ourself as address already
   address_havelevel[NEW.rank_address] := true;
   -- RAISE WARNING '  getNearFeatures(%,''%'',%,''%'')',NEW.partition, place_centroid, search_maxrank, isin_tokens;
-  FOR location IN SELECT * from getNearFeatures(NEW.partition, place_centroid, search_maxrank, isin_tokens) LOOP
+  FOR location IN
+    SELECT * from getNearFeatures(NEW.partition,
+                                  CASE WHEN NEW.rank_search >= 26 THEN NEW.geometry
+                                  ELSE place_centroid END,
+                                  search_maxrank, isin_tokens)
+  LOOP
 
 --RAISE WARNING '  AREA: %',location;
 
 
 --RAISE WARNING '  AREA: %',location;
 
index a0181c0a2680ba79195ec3e814dbabac8ededcca..46dc6137ee7884332b3a47efd7f5ccaea0767723 100644 (file)
@@ -1,4 +1,4 @@
-create or replace function getNearFeatures(in_partition INTEGER, point GEOMETRY, maxrank INTEGER, isin_tokens INT[]) RETURNS setof nearfeaturecentr AS $$
+create or replace function getNearFeatures(in_partition INTEGER, feature GEOMETRY, maxrank INTEGER, isin_tokens INT[]) RETURNS setof nearfeaturecentr AS $$
 DECLARE
   r nearfeaturecentr%rowtype;
 BEGIN
 DECLARE
   r nearfeaturecentr%rowtype;
 BEGIN
@@ -6,14 +6,14 @@ BEGIN
 -- start
   IF in_partition = -partition- THEN
     FOR r IN 
 -- start
   IF in_partition = -partition- THEN
     FOR r IN 
-      SELECT place_id, keywords, rank_address, rank_search, min(ST_Distance(point, centroid)) as distance, isguess, centroid FROM (
-        SELECT * FROM location_area_large_-partition- WHERE ST_Contains(geometry, point) and rank_search < maxrank
+      SELECT place_id, keywords, rank_address, rank_search, min(ST_Distance(feature, centroid)) as distance, isguess, centroid FROM (
+        SELECT * FROM location_area_large_-partition- WHERE ST_Intersects(geometry, feature) and rank_search < maxrank
         UNION ALL
         UNION ALL
-        SELECT * FROM location_area_country WHERE ST_Contains(geometry, point) and rank_search < maxrank
+        SELECT * FROM location_area_country WHERE ST_Intersects(geometry, feature) and rank_search < maxrank
       ) as location_area
       GROUP BY place_id, keywords, rank_address, rank_search, isguess, centroid
       ORDER BY rank_address, isin_tokens && keywords desc, isguess asc,
       ) as location_area
       GROUP BY place_id, keywords, rank_address, rank_search, isguess, centroid
       ORDER BY rank_address, isin_tokens && keywords desc, isguess asc,
-        ST_Distance(point, centroid) * 
+        ST_Distance(feature, centroid) *
           CASE 
                WHEN rank_address = 16 AND rank_search = 15 THEN 0.2 -- capital city
                WHEN rank_address = 16 AND rank_search = 16 THEN 0.25 -- city
           CASE 
                WHEN rank_address = 16 AND rank_search = 15 THEN 0.2 -- capital city
                WHEN rank_address = 16 AND rank_search = 16 THEN 0.25 -- city
diff --git a/test/bdd/db/import/addressing.feature b/test/bdd/db/import/addressing.feature
new file mode 100644 (file)
index 0000000..2bff824
--- /dev/null
@@ -0,0 +1,22 @@
+@DB
+Feature: Address computation
+    Tests for filling of place_addressline
+
+    # github #121
+    Scenario: Roads crossing boundaries should contain both states
+        Given the grid
+            | 1 |   |   | 2 |   | 3 |
+            |   | 7 |   | 8 |   |   |
+            | 4 |   |   | 5 |   | 6 |
+        And the named places
+            | osm | class   | type | geometry |
+            | W1  | highway | road | 7, 8     |
+        And the named places
+            | osm | class    | type           | admin | geometry      |
+            | W10 | boundary | administrative | 5     | (1, 2, 5, 4, 1) |
+            | W11 | boundary | administrative | 5     | (2, 3, 6, 5, 2) |
+        When importing
+        Then place_addressline contains
+            | object | address | cached_rank_address |
+            | W1     | W10     | 10                  |
+            | W1     | W11     | 10                  |
index 869cf829825fce1212ffea6acc437a1cf3266d53..df1d1688f8428bd1006ce2b9fe05aeacf8ee0c17 100644 (file)
@@ -93,6 +93,12 @@ class NominatimID:
             self.oid = m.group('id')
             self.cls = m.group('cls')
 
             self.oid = m.group('id')
             self.cls = m.group('cls')
 
+    def __str__(self):
+        if self.cls is None:
+            return self.typ + self.oid
+
+        return '%s%d:%s' % (self.typ, self.oid, self.cls)
+
     def table_select(self):
         """ Return where clause and parameter list to select the object
             from a Nominatim table.
     def table_select(self):
         """ Return where clause and parameter list to select the object
             from a Nominatim table.
@@ -109,7 +115,9 @@ class NominatimID:
     def get_place_id(self, cur):
         where, params = self.table_select()
         cur.execute("SELECT place_id FROM placex WHERE %s" % where, params)
     def get_place_id(self, cur):
         where, params = self.table_select()
         cur.execute("SELECT place_id FROM placex WHERE %s" % where, params)
-        eq_(1, cur.rowcount, "Expected exactly 1 entry in placex found %s" % cur.rowcount)
+        eq_(1, cur.rowcount,
+            "Expected exactly 1 entry in placex for %s found %s"
+              % (str(self), cur.rowcount))
 
         return cur.fetchone()[0]
 
 
         return cur.fetchone()[0]
 
@@ -386,6 +394,27 @@ def check_search_name_contents(context):
 
     context.db.commit()
 
 
     context.db.commit()
 
+@then("place_addressline contains")
+def check_place_addressline(context):
+    cur = context.db.cursor(cursor_factory=psycopg2.extras.DictCursor)
+
+    for row in context.table:
+        pid = NominatimID(row['object']).get_place_id(cur)
+        apid = NominatimID(row['address']).get_place_id(cur)
+        cur.execute(""" SELECT * FROM place_addressline
+                        WHERE place_id = %s AND address_place_id = %s""",
+                    (pid, apid))
+        assert_less(0, cur.rowcount,
+                    "No rows found for place %s and address %s"
+                      % (row['object'], row['address']))
+
+        for res in cur:
+            for h in row.headings:
+                if h not in ('address', 'object'):
+                    assert_db_column(res, h, row[h], context)
+
+    context.db.commit()
+
 @then("(?P<oid>\w+) expands to(?P<neg> no)? interpolation")
 def check_location_property_osmline(context, oid, neg):
     cur = context.db.cursor(cursor_factory=psycopg2.extras.DictCursor)
 @then("(?P<oid>\w+) expands to(?P<neg> no)? interpolation")
 def check_location_property_osmline(context, oid, neg):
     cur = context.db.cursor(cursor_factory=psycopg2.extras.DictCursor)