diff --git a/helper/diffPlaces.js b/helper/diffPlaces.js index 537a2d960..6909034f2 100644 --- a/helper/diffPlaces.js +++ b/helper/diffPlaces.js @@ -46,6 +46,26 @@ function isUsState(item) { return item.parent.country_a[0] === 'USA' && item.layer === 'region'; } +// Geonames records in the locality and localadmin layer are parented by themselves +// This breaks our other hierarchy logic, so check for this special case +function isGeonamesWithSelfParent(item, placeType) { + if (item.source !== 'geonames') { return false; } + if (item.layer !== placeType) { return false; } + + if (!item.parent) { return false; } + + // get the relevant parent id(s) for the placeType in question + const parent_records = item.parent[`${placeType}_id`] || []; + + // check if the parent ids at this layer match this Geonames record + // we have special cased Geonames parents in many cases + // handle both array and scalar values + if (item.source_id === parent_records) { return true; } + if (parent_records.includes(item.source_id)) { return true; } + + return false; +} + /** * Compare the parent properties if they exist. * Returns false if the objects are the same, else true. @@ -108,6 +128,11 @@ function isParentHierarchyDifferent(item1, item2){ // skip layers that are more granular than $maxRank if (rank > maxRank){ return false; } + // Special case Geonames records that are parented by themselves and would otherwise break these checks + if (isGeonamesWithSelfParent(item1, placeType) || isGeonamesWithSelfParent(item2, placeType)) { + return false; + } + // ensure the parent ids are the same for all placetypes return isPropertyDifferent( parent1, parent2, `${placeType}_id` ); }); diff --git a/test/unit/helper/diffPlaces.js b/test/unit/helper/diffPlaces.js index 5910219bb..3ad68b95a 100644 --- a/test/unit/helper/diffPlaces.js +++ b/test/unit/helper/diffPlaces.js @@ -790,6 +790,40 @@ module.exports.tests.geonames = function (test, common) { }); }; +module.exports.tests.geonames_self_parent = function (test, common) { + test('geonames records that parent themselves should not break hierarchy checks', function(t) { + const gn_record = { + source: 'geonames', + layer: 'localadmin', + source_id: '7163824', + name: { + default: 'City of New York' + }, + parent: { + country_id: ['85633793'], // USA, WOF + region_id: ['85688543'], // NY, WOF + localadmin_id: ['7163824'] // New York County, Geonames + } + }; + const wof_record = { + source: 'whosonfirst', + layer: 'locality', + source_id: '85977539', + name: { + default: 'New York' + }, + parent: { + country_id: ['85633793'], // USA, WOF + region_id: ['85688543'], // NY, WOF + //localadmin_id: null // no localadmin is set for NYC in WOF + } + }; + + t.false(isDifferent(gn_record, wof_record), 'should be the same based on hierarchy'); + t.end(); + }); +}; + module.exports.all = function (tape, common) { function test(name, testFunction) {