1
1
const _ = require ( 'lodash' ) ;
2
2
3
- const defaultLabelGenerator = require ( 'pelias-labels' ) ;
3
+ const defaultLabelGenerator = require ( 'pelias-labels' ) . partsGenerator ;
4
4
5
5
function setup ( labelGenerator ) {
6
6
function middleware ( req , res , next ) {
@@ -10,17 +10,66 @@ function setup(labelGenerator) {
10
10
return middleware ;
11
11
}
12
12
13
+ function getLabelFromLayer ( labelParts , layer ) {
14
+ const part = labelParts . find ( p => p . layer === layer ) ;
15
+ return _ . get ( part , 'label' ) ;
16
+ }
17
+
18
+ function filterUnambiguousParts ( second ) {
19
+ return ( labelParts ) => {
20
+ if ( labelParts . role === 'required' ) {
21
+ return false ;
22
+ }
23
+ const label = getLabelFromLayer ( second . labelParts , labelParts . layer ) ;
24
+ return label && label !== labelParts . label ;
25
+ } ;
26
+ }
27
+
28
+ function getBestLayers ( results ) {
29
+ const bestLayers = new Set ( ) ;
30
+ const first = results [ 0 ] ;
31
+ // Ensure deduplication based on optional elements even when the first two elements are equals.
32
+ for ( let i = 1 ; i < results . length ; i ++ ) {
33
+ const second = results [ i ] ;
34
+ first . labelParts . filter ( filterUnambiguousParts ( second ) ) . map ( ( p ) => bestLayers . add ( p . layer ) ) ;
35
+ if ( bestLayers . size > 0 ) {
36
+ // For now, we break as soon as we find a discriminant.
37
+ break ;
38
+ }
39
+ }
40
+ return bestLayers ;
41
+ }
42
+
13
43
function assignLabel ( req , res , next , labelGenerator ) {
14
44
15
45
// do nothing if there's nothing to process
16
46
if ( ! res || ! res . data ) {
17
47
return next ( ) ;
18
48
}
19
49
50
+ // This object will help for label deduplication
51
+ const dedupLabel = { } ;
52
+
53
+ // First we assign for all result the default label with all required layers
20
54
res . data . forEach ( function ( result ) {
21
- result . label = labelGenerator ( result , _ . get ( req , 'clean.lang.iso6393' ) ) ;
55
+ const { labelParts, separator } = labelGenerator ( result , _ . get ( req , 'clean.lang.iso6393' ) ) ;
56
+ result . label = labelParts . filter ( e => e . role === 'required' ) . map ( e => e . label ) . join ( separator ) ;
57
+ dedupLabel [ result . label ] = dedupLabel [ result . label ] || [ ] ;
58
+ dedupLabel [ result . label ] . push ( { result, labelParts, separator } ) ;
22
59
} ) ;
23
60
61
+ // We check all values with more than one entry
62
+ Object . values ( dedupLabel )
63
+ . filter ( results => results . length > 1 )
64
+ . forEach ( results => {
65
+ // This array will contain all optional layers that should be displayed
66
+ const bestLayers = getBestLayers ( results ) ;
67
+ // We reassign the label with the new value
68
+ results . forEach ( ( { result, labelParts, separator } ) => {
69
+ result . label = labelParts . filter ( e => e . role === 'required' || bestLayers . has ( e . layer ) ) . map ( e => e . label ) . join ( separator ) ;
70
+ } ) ;
71
+ } ) ;
72
+
24
73
next ( ) ;
25
74
}
26
75
0 commit comments