Skip to content

Commit

Permalink
feat(assignLabels): improve duplicate label handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Joxit committed May 19, 2022
1 parent 8d72ac1 commit fd1d0e5
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 8 deletions.
53 changes: 51 additions & 2 deletions middleware/assignLabels.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const _ = require('lodash');

const defaultLabelGenerator = require('pelias-labels');
const defaultLabelGenerator = require('pelias-labels').partsGenerator;

function setup(labelGenerator) {
function middleware(req, res, next) {
Expand All @@ -10,17 +10,66 @@ function setup(labelGenerator) {
return middleware;
}

function getLabelFromLayer(labelParts, layer) {
const part = labelParts.find(p => p.layer === layer);
return _.get(part, 'label');
}

function filterUnambiguousParts(second) {
return (labelParts) => {
if (labelParts.role === 'required') {
return false;
}
const label = getLabelFromLayer(second.labelParts, labelParts.layer);
return label && label !== labelParts.label;
};
}

function getBestLayers(results) {
const bestLayers = new Set();
const first = results[0];
// Ensure deduplication based on optional elements even when the first two elements are equals.
for (let i = 1; i < results.length; i++) {
const second = results[i];
first.labelParts.filter(filterUnambiguousParts(second)).map((p) => bestLayers.add(p.layer));
if (bestLayers.size > 0) {
// For now, we break as soon as we find a discriminant.
break;
}
}
return bestLayers;
}

function assignLabel(req, res, next, labelGenerator) {

// do nothing if there's nothing to process
if (!res || !res.data) {
return next();
}

// This object will help for label deduplication
const dedupLabel = {};

// First we assign for all result the default label with all required layers
res.data.forEach(function (result) {
result.label = labelGenerator(result, _.get(req, 'clean.lang.iso6393'));
const { labelParts, separator } = labelGenerator(result, _.get(req, 'clean.lang.iso6393'));
result.label = labelParts.filter(e => e.role === 'required').map(e => e.label).join(separator);
dedupLabel[result.label] = dedupLabel[result.label] || [];
dedupLabel[result.label].push({ result, labelParts, separator });
});

// We check all values with more than one entry
Object.values(dedupLabel)
.filter(results => results.length > 1)
.forEach(results => {
// This array will contain all optional layers that should be displayed
const bestLayers = getBestLayers(results);
// We reassign the label with the new value
results.forEach(({ result, labelParts, separator }) => {
result.label = labelParts.filter(e => e.role === 'required' || bestLayers.has(e.layer)).map(e => e.label).join(separator);
});
});

next();
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"morgan": "^1.8.2",
"pelias-compare": "^0.1.16",
"pelias-config": "^5.0.1",
"pelias-labels": "^1.19.0",
"pelias-labels": "pelias/labels#joxit/feat/with-optional",
"pelias-logger": "^1.2.0",
"pelias-microservice-wrapper": "^1.10.0",
"pelias-model": "^9.0.0",
Expand Down
14 changes: 9 additions & 5 deletions test/unit/middleware/assignLabels.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
var proxyquire = require('proxyquire').noCallThru();

function partsGenerator(cb) {
return { partsGenerator: cb };
}

module.exports.tests = {};

module.exports.tests.serialization = function(test, common) {
Expand Down Expand Up @@ -30,10 +34,10 @@ module.exports.tests.serialization = function(test, common) {
test('labels should be assigned to all results', function(t) {
var labelGenerator = function(result) {
if (result.id === 1) {
return 'label 1';
return { labelParts: [{ label: 'label 1', role: 'required' }], separator: ', '};
}
if (result.id === 2) {
return 'label 2';
return { labelParts: [{ label: 'label 2', role: 'required' }], separator: ', '};
}

};
Expand Down Expand Up @@ -73,11 +77,11 @@ module.exports.tests.serialization = function(test, common) {

test('no explicit labelGenerator supplied should use pelias-labels module', function(t) {
var assignLabels = proxyquire('../../../middleware/assignLabels', {
'pelias-labels': function(result) {
'pelias-labels': partsGenerator(function(result) {
if (result.id === 1) {
return 'label 1';
return { labelParts: [{ label: 'label 1', role: 'required' }], separator: ', '};
}
}
})
})();

var input = {
Expand Down

0 comments on commit fd1d0e5

Please sign in to comment.