mirror of https://github.com/pelias/api.git
Diana Shkolnikov
8 years ago
committed by
Stephen Hess
6 changed files with 1394 additions and 310 deletions
@ -0,0 +1,172 @@
|
||||
var _ = require('lodash'); |
||||
var placeTypes = require('../helper/placeTypes'); |
||||
|
||||
/** |
||||
* Compare the layer properties if they exist. |
||||
* Returns false if the objects are the same, and throws |
||||
* an exception with the message 'different' if not. |
||||
* |
||||
* @param {object} item1 |
||||
* @param {object} item2 |
||||
* @returns {boolean} |
||||
* @throws {Error} |
||||
*/ |
||||
function isDiffLayer(item1, item2) { |
||||
if (item1.layer === item2.layer) { |
||||
return false; |
||||
} |
||||
|
||||
throw new Error('different'); |
||||
} |
||||
|
||||
/** |
||||
* Compare the parent.* properties if they exist. |
||||
* Returns false if the objects are the same, and throws |
||||
* an exception with the message 'different' if not. |
||||
* |
||||
* @param {object} item1 |
||||
* @param {object} item2 |
||||
* @returns {boolean} |
||||
* @throws {Error} |
||||
*/ |
||||
function isDiffParentHierarchy(item1, item2) { |
||||
// if neither object has parent, assume same
|
||||
if (!item1.hasOwnProperty('parent') && !item2.hasOwnProperty('parent')) { |
||||
return false; |
||||
} |
||||
|
||||
// if both have parent, do the rest of the checking
|
||||
if (item1.hasOwnProperty('parent') && item2.hasOwnProperty('parent')) { |
||||
placeTypes.forEach(function (placeType) { |
||||
// don't consider its own id
|
||||
if (placeType === item1.layer) { |
||||
return; |
||||
} |
||||
propMatch(item1.parent, item2.parent, placeType + '_id'); |
||||
}); |
||||
return false; |
||||
} |
||||
|
||||
// if one has parent and the other doesn't consider different
|
||||
throw new Error('different'); |
||||
} |
||||
|
||||
/** |
||||
* Compare the name.* properties if they exist. |
||||
* Returns false if the objects are the same, and throws |
||||
* an exception with the message 'different' if not. |
||||
* |
||||
* @param {object} item1 |
||||
* @param {object} item2 |
||||
* @returns {boolean} |
||||
* @throws {Error} |
||||
*/ |
||||
function isDiffName(item1, item2) { |
||||
if (item1.hasOwnProperty('name') && item2.hasOwnProperty('name')) { |
||||
for (var lang in item1.name) { |
||||
if(item2.name[lang] || lang === 'default') { |
||||
// do not consider absence of an additional name as a difference
|
||||
propMatch(item1.name, item2.name, lang); |
||||
} |
||||
} |
||||
} |
||||
else { |
||||
propMatch(item1, item2, 'name'); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Compare the address_parts properties if they exist. |
||||
* Returns false if the objects are the same, and throws |
||||
* an exception with the message 'different' if not. |
||||
* |
||||
* @param {object} item1 |
||||
* @param {object} item2 |
||||
* @returns {boolean} |
||||
* @throws {Error} |
||||
*/ |
||||
function isDiffAddress(item1, item2) { |
||||
// if neither record has address, assume same
|
||||
if (!item1.hasOwnProperty('address_parts') && !item2.hasOwnProperty('address_parts')) { |
||||
return false; |
||||
} |
||||
|
||||
// if both have address, check parts
|
||||
if (item1.hasOwnProperty('address_parts') && item2.hasOwnProperty('address_parts')) { |
||||
propMatch(item1.address_parts, item2.address_parts, 'number'); |
||||
propMatch(item1.address_parts, item2.address_parts, 'street'); |
||||
|
||||
// only compare zip if both records have it, otherwise just ignore and assume it's the same
|
||||
// since by this time we've already compared parent hierarchies
|
||||
if (item1.address_parts.hasOwnProperty('zip') && item2.address_parts.hasOwnProperty('zip')) { |
||||
propMatch(item1.address_parts, item2.address_parts, 'zip'); |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
// one has address and the other doesn't, different!
|
||||
throw new Error('different'); |
||||
} |
||||
|
||||
/** |
||||
* Compare the two records and return true if they differ and false if same. |
||||
* |
||||
* @param {object} item1 |
||||
* @param {object} item2 |
||||
* @returns {boolean} |
||||
* @throws {Error} |
||||
*/ |
||||
function isDifferent(item1, item2) { |
||||
try { |
||||
isDiffLayer(item1, item2); |
||||
isDiffParentHierarchy(item1, item2); |
||||
isDiffName(item1, item2); |
||||
isDiffAddress(item1, item2); |
||||
} |
||||
catch (err) { |
||||
if (err.message === 'different') { |
||||
return true; |
||||
} |
||||
throw err; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Throw exception if properties are different |
||||
* |
||||
* @param {object} item1 |
||||
* @param {object} item2 |
||||
* @param {string} prop |
||||
* @throws {Error} |
||||
*/ |
||||
function propMatch(item1, item2, prop) { |
||||
var prop1 = item1[prop]; |
||||
var prop2 = item2[prop]; |
||||
|
||||
// in the case the property is an array (currently only in parent schema)
|
||||
// simply take the 1st item. this will change in the near future to support multiple hierarchies
|
||||
if (_.isArray(prop1)) { prop1 = prop1[0]; } |
||||
if (_.isArray(prop2)) { prop2 = prop2[0]; } |
||||
|
||||
if (normalizeString(prop1) !== normalizeString(prop2)) { |
||||
throw new Error('different'); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Remove punctuation and lowercase |
||||
* |
||||
* @param {string} str |
||||
* @returns {string} |
||||
*/ |
||||
function normalizeString(str) { |
||||
if (!str) { |
||||
return ''; |
||||
} |
||||
return str.toLowerCase().split(/[ ,-]+/).join(' '); |
||||
} |
||||
|
||||
module.exports.isDifferent = isDifferent; |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,180 @@
|
||||
var isDifferent= require('../../../helper/diffPlaces').isDifferent; |
||||
|
||||
module.exports.tests = {}; |
||||
|
||||
module.exports.tests.dedupe = function(test, common) { |
||||
|
||||
test('match same object', function(t) { |
||||
var item1 = { |
||||
'parent': { |
||||
'country': [ 'United States' ], |
||||
'county': [ 'Otsego County' ], |
||||
'region_a': [ 'NY' ], |
||||
'localadmin': [ 'Cherry Valley' ], |
||||
'county_id': [ '102082399' ], |
||||
'localadmin_id': [ '404522887' ], |
||||
'country_a': [ 'USA' ], |
||||
'region_id': [ '85688543' ], |
||||
'locality': [ 'Cherry Valley' ], |
||||
'locality_id': [ '85978799' ], |
||||
'region': [ 'New York' ], |
||||
'country_id': [ '85633793' ] |
||||
}, |
||||
'name': { |
||||
'default': '1 Main Street' |
||||
}, |
||||
'address_parts': { |
||||
'number': '1', |
||||
'street': 'Main Street' |
||||
}, |
||||
'layer': 'address' |
||||
}; |
||||
|
||||
t.false(isDifferent(item1, item1), 'should be the same'); |
||||
t.end(); |
||||
}); |
||||
|
||||
test('catch diff layers', function(t) { |
||||
var item1 = { 'layer': 'address' }; |
||||
var item2 = { 'layer': 'venue' }; |
||||
|
||||
t.true(isDifferent(item1, item2), 'should be different'); |
||||
t.end(); |
||||
}); |
||||
|
||||
test('catch diff parent', function(t) { |
||||
var item1 = { |
||||
'layer': 'same', |
||||
'parent': { |
||||
'country_id': '12345' |
||||
} |
||||
}; |
||||
var item2 = { |
||||
'layer': 'same', |
||||
'parent': { |
||||
'country_id': '54321' |
||||
} |
||||
}; |
||||
|
||||
t.true(isDifferent(item1, item2), 'should be different'); |
||||
t.end(); |
||||
}); |
||||
|
||||
test('catch diff name', function(t) { |
||||
var item1 = { |
||||
'name': { |
||||
'default': '1 Main St' |
||||
} |
||||
}; |
||||
var item2 = { |
||||
'name': { |
||||
'default': '1 Broad St' |
||||
} |
||||
}; |
||||
|
||||
t.true(isDifferent(item1, item2), 'should be different'); |
||||
t.end(); |
||||
}); |
||||
|
||||
test('match diff capitalization in name', function(t) { |
||||
var item1 = { |
||||
'name': { |
||||
'default': '1 MAIN ST' |
||||
} |
||||
}; |
||||
var item2 = { |
||||
'name': { |
||||
'default': '1 Main St' |
||||
} |
||||
}; |
||||
|
||||
t.false(isDifferent(item1, item2), 'should be the same'); |
||||
t.end(); |
||||
}); |
||||
|
||||
test('do not handle expansions', function(t) { |
||||
// we currently don't handle expansions and abbreviations and
|
||||
// this is a test waiting to be updated as soon as we fix it
|
||||
|
||||
var item1 = { |
||||
'name': { |
||||
'default': '1 Main Street' |
||||
} |
||||
}; |
||||
var item2 = { |
||||
'name': { |
||||
'default': '1 Main St' |
||||
} |
||||
}; |
||||
|
||||
t.true(isDifferent(item1, item2), 'should be different'); |
||||
t.end(); |
||||
}); |
||||
|
||||
test('missing names in other langs should not be a diff', function(t) { |
||||
var item1 = { |
||||
'name': { |
||||
'default': 'Moscow', |
||||
'rus': 'Москва' |
||||
} |
||||
}; |
||||
var item2 = { |
||||
'name': { |
||||
'default': 'Moscow' |
||||
} |
||||
}; |
||||
|
||||
t.false(isDifferent(item1, item2), 'should be the same'); |
||||
t.end(); |
||||
}); |
||||
|
||||
test('catch diff address', function(t) { |
||||
var item1 = { |
||||
'address_parts': { |
||||
'number': '1', |
||||
'street': 'Main Street', |
||||
'zip': '90210' |
||||
} |
||||
}; |
||||
var item2 = { |
||||
'address_parts': { |
||||
'number': '2', |
||||
'street': 'Main Street', |
||||
'zip': '90210' |
||||
} |
||||
}; |
||||
|
||||
t.true(isDifferent(item1, item2), 'should be different'); |
||||
t.end(); |
||||
}); |
||||
|
||||
test('catch diff address', function(t) { |
||||
var item1 = { |
||||
'address_parts': { |
||||
'number': '1', |
||||
'street': 'Main Street', |
||||
'zip': '90210' |
||||
} |
||||
}; |
||||
var item2 = { |
||||
'address_parts': { |
||||
'number': '1', |
||||
'street': 'Main Street' |
||||
} |
||||
}; |
||||
|
||||
t.false(isDifferent(item1, item2), 'should be the same'); |
||||
t.end(); |
||||
}); |
||||
}; |
||||
|
||||
module.exports.all = function (tape, common) { |
||||
|
||||
function test(name, testFunction) { |
||||
return tape('[helper] diffPlaces: ' + name, testFunction); |
||||
} |
||||
|
||||
for( var testCase in module.exports.tests ){ |
||||
module.exports.tests[testCase](test, common); |
||||
} |
||||
}; |
Loading…
Reference in new issue