From a3517e2787ef9de3775b4305585a5c6209fd06b6 Mon Sep 17 00:00:00 2001 From: Sarah Hoffmann Date: Wed, 26 Feb 2025 10:47:32 +0100 Subject: [PATCH] take postcodes from postcode relations into account The correct order for resolving postcodes is: 1. addr:postcode tag 2. postcode from boundary=postal_code relation 3. computed postcode for object --- src/main/java/de/komoot/photon/PhotonDoc.java | 27 +++++----- .../photon/nominatim/model/AddressRow.java | 2 +- .../nominatim/NominatimConnectorDBTest.java | 54 +++++++++++++++++++ .../nominatim/testdb/PlacexTestRow.java | 12 +++-- 4 files changed, 76 insertions(+), 19 deletions(-) diff --git a/src/main/java/de/komoot/photon/PhotonDoc.java b/src/main/java/de/komoot/photon/PhotonDoc.java index 43b90cf4..f2568394 100644 --- a/src/main/java/de/komoot/photon/PhotonDoc.java +++ b/src/main/java/de/komoot/photon/PhotonDoc.java @@ -104,11 +104,7 @@ public PhotonDoc address(Map address) { extractAddress(address, AddressType.COUNTY, "county"); extractAddress(address, AddressType.STATE, "state"); - String addressPostCode = address.get("postcode"); - if (addressPostCode != null && !addressPostCode.equals(postcode)) { - LOGGER.debug("Replacing postcode {} with {} for osmId #{}", postcode, addressPostCode, osmId); - postcode = addressPostCode; - } + postcode = address.getOrDefault("postcode", postcode); } return this; } @@ -211,9 +207,6 @@ public boolean isUsefulForIndex() { * * @param addressType The type of address field to fill. * @param addressFieldName The name of the address tag to use (without the 'addr:' prefix). - * - * @return 'existingField' potentially with the name field replaced. If existingField was null and - * the address field could be found, then a new map with the address as single entry is returned. */ private void extractAddress(Map address, AddressType addressType, String addressFieldName) { String field = address.get(addressFieldName); @@ -258,13 +251,17 @@ public boolean setAddressPartIfNew(AddressType addressType, Map public void completePlace(List addresses) { final AddressType doctype = getAddressType(); for (AddressRow address : addresses) { - final AddressType atype = address.getAddressType(); - - if (atype != null - && (atype == doctype || !setAddressPartIfNew(atype, address.getName())) - && address.isUsefulForContext()) { - // no specifically handled item, check if useful for context - getContext().add(address.getName()); + if (address.isPostcode()) { + this.postcode = address.getName().getOrDefault("ref", this.postcode); + } else { + final AddressType atype = address.getAddressType(); + + if (atype != null + && (atype == doctype || !setAddressPartIfNew(atype, address.getName())) + && address.isUsefulForContext()) { + // no specifically handled item, check if useful for context + getContext().add(address.getName()); + } } } } diff --git a/src/main/java/de/komoot/photon/nominatim/model/AddressRow.java b/src/main/java/de/komoot/photon/nominatim/model/AddressRow.java index a693b687..c5b2a9b9 100644 --- a/src/main/java/de/komoot/photon/nominatim/model/AddressRow.java +++ b/src/main/java/de/komoot/photon/nominatim/model/AddressRow.java @@ -22,7 +22,7 @@ public AddressType getAddressType() { return AddressType.fromRank(rankAddress); } - private boolean isPostcode() { + public boolean isPostcode() { if ("place".equals(osmKey) && "postcode".equals(osmValue)) { return true; } diff --git a/src/test/java/de/komoot/photon/nominatim/NominatimConnectorDBTest.java b/src/test/java/de/komoot/photon/nominatim/NominatimConnectorDBTest.java index f2bd4ddf..6b32e449 100644 --- a/src/test/java/de/komoot/photon/nominatim/NominatimConnectorDBTest.java +++ b/src/test/java/de/komoot/photon/nominatim/NominatimConnectorDBTest.java @@ -360,6 +360,60 @@ void testNoCountry() { assertNull(importer.get(place).getCountryCode()); } + @Test + void testUsePostcodeFromPlacex() { + PlacexTestRow parent = PlacexTestRow.make_street("Main St").add(jdbc); + PlacexTestRow place = new PlacexTestRow("building", "yes") + .addr("housenumber", "34") + .postcode("AA 44XH") + .parent(parent).add(jdbc); + + readEntireDatabase(); + + PhotonDoc result = importer.get(place); + + assertEquals("AA 44XH", result.getPostcode()); + } + + @Test + void testPreferPostcodeFromPostcodeRelations() { + PlacexTestRow parent = PlacexTestRow.make_street("Main St").add(jdbc); + PlacexTestRow place = new PlacexTestRow("building", "yes") + .addr("housenumber", "34") + .postcode("XXX") + .parent(parent).add(jdbc); + PlacexTestRow postcode = new PlacexTestRow("boundary", "postal_code") + .name("ref", "1234XZ").ranks(11).add(jdbc); + + parent.addAddresslines(jdbc, postcode); + + readEntireDatabase(); + + PhotonDoc result = importer.get(place); + + assertEquals("1234XZ", result.getPostcode()); + } + + @Test + void testPreferPostcodeFromAddress() { + PlacexTestRow parent = PlacexTestRow.make_street("Main St").add(jdbc); + PlacexTestRow place = new PlacexTestRow("building", "yes") + .addr("housenumber", "34") + .addr("postcode", "45-234") + .postcode("XXX") + .parent(parent).add(jdbc); + PlacexTestRow postcode = new PlacexTestRow("boundary", "postal_code") + .name("ref", "1234XZ").ranks(11).add(jdbc); + + parent.addAddresslines(jdbc, postcode); + + readEntireDatabase(); + + PhotonDoc result = importer.get(place); + + assertEquals("45-234", result.getPostcode()); + } + @Test void testGetImportDate() { Date importDate = connector.getLastImportDate(); diff --git a/src/test/java/de/komoot/photon/nominatim/testdb/PlacexTestRow.java b/src/test/java/de/komoot/photon/nominatim/testdb/PlacexTestRow.java index 85a14553..a505d190 100644 --- a/src/test/java/de/komoot/photon/nominatim/testdb/PlacexTestRow.java +++ b/src/test/java/de/komoot/photon/nominatim/testdb/PlacexTestRow.java @@ -23,6 +23,7 @@ public class PlacexTestRow { private Integer rankAddress = 30; private Integer rankSearch = 30; private String centroid; + private String postcode; private String countryCode = "us"; private Double importance = null; @@ -115,12 +116,17 @@ public PlacexTestRow parent(PlacexTestRow row) { return this; } + public PlacexTestRow postcode(String postcode) { + this.postcode = postcode; + return this; + } + public PlacexTestRow add(JdbcTemplate jdbc) { jdbc.update("INSERT INTO placex (place_id, parent_place_id, osm_type, osm_id, class, type, rank_search, rank_address," - + " centroid, name, country_code, importance, address, indexed_status)" - + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ? FORMAT JSON, ?, ?, ? FORMAT JSON, 0)", + + " centroid, name, country_code, importance, address, postcode, indexed_status)" + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ? FORMAT JSON, ?, ?, ? FORMAT JSON, ?, 0)", placeId, parentPlaceId, osmType, osmId, key, value, rankSearch, rankAddress, centroid, - asJson(names), countryCode, importance, asJson(address)); + asJson(names), countryCode, importance, asJson(address), postcode); return this; }