pelias-openstreetmap 8.3.1 → 8.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jshintrc +2 -2
- package/README.md +20 -0
- package/config/addendum_whitelist.js +25 -0
- package/config/features.js +54 -46
- package/package.json +3 -1
- package/schema.js +8 -1
- package/scripts/generate_taginfo.js +154 -0
- package/stream/addendum_mapper.js +1 -17
- package/stream/document_constructor.js +9 -2
- package/stream/importPipeline.js +2 -0
- package/stream/pbf.js +6 -6
- package/stream/venueFilter.js +30 -0
- package/taginfo.json +590 -0
- package/util/layerClassifier.js +44 -0
- package/util/resolveFeatures.js +25 -0
package/.jshintrc
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
"esversion": 6,
|
|
3
2
|
"node": true,
|
|
4
3
|
"curly": true,
|
|
5
4
|
"eqeqeq": true,
|
|
5
|
+
"esversion": 11,
|
|
6
6
|
"freeze": true,
|
|
7
7
|
"immed": true,
|
|
8
8
|
"indent": 2,
|
|
@@ -17,6 +17,6 @@
|
|
|
17
17
|
"undef": true,
|
|
18
18
|
"unused": false,
|
|
19
19
|
"maxparams": 4,
|
|
20
|
-
"maxdepth":
|
|
20
|
+
"maxdepth": 4,
|
|
21
21
|
"maxlen": 140
|
|
22
22
|
}
|
package/README.md
CHANGED
|
@@ -94,6 +94,24 @@ The OSM importer will look for a file with a name matching this value in the con
|
|
|
94
94
|
|
|
95
95
|
If downloading from a remote URL, the filename must match the value in `sourceURL`.
|
|
96
96
|
|
|
97
|
+
#### `imports.openstreetmap.layers`
|
|
98
|
+
|
|
99
|
+
This is an object you can use to define your own layers based on OSM tags. For example, if you wanted a layer `coffee` for just coffee shops you could set:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
{
|
|
103
|
+
"imports": {
|
|
104
|
+
"openstreetmap": {
|
|
105
|
+
"layers": {
|
|
106
|
+
"coffee": {
|
|
107
|
+
"tags": [ "amenity~cafe+name" ]
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
97
115
|
#### `imports.openstreetmap.leveldbpath`
|
|
98
116
|
|
|
99
117
|
This is the directory where temporary files will be stored in order to
|
|
@@ -106,6 +124,8 @@ Defaults to `tmp`.
|
|
|
106
124
|
|
|
107
125
|
By default, the OSM importer imports both venue records and addresses. If set to false, only address records will be imported.
|
|
108
126
|
|
|
127
|
+
You can also disable venue import by setting `imports.openstreetmap.layers.venue` to an empty value.
|
|
128
|
+
|
|
109
129
|
#### `imports.openstreetmap.removeDisusedVenues`
|
|
110
130
|
|
|
111
131
|
If set to boolean `true`, `venue`s with popularity below `0` (as determined by OSM tags) will be
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
Tags stored verbatim in the OSM addendum of every imported record.
|
|
4
|
+
|
|
5
|
+
@see stream/addendum_mapper.js
|
|
6
|
+
@see https://github.com/pelias/api/pull/1255
|
|
7
|
+
**/
|
|
8
|
+
|
|
9
|
+
module.exports = [
|
|
10
|
+
'wheelchair', // Wheelchair accessibility
|
|
11
|
+
'iata', // IATA airport codes
|
|
12
|
+
'icao', // ICAO airport codes
|
|
13
|
+
'wikidata', // Wikidata concordance
|
|
14
|
+
'wikipedia', // Wikipedia concordance
|
|
15
|
+
'operator', // Operator name
|
|
16
|
+
'brand', // Brand name
|
|
17
|
+
'website', // Website URL
|
|
18
|
+
'phone', // Telephone number
|
|
19
|
+
'opening_hours', // Opening hours
|
|
20
|
+
|
|
21
|
+
// COVID-19
|
|
22
|
+
'opening_hours:covid19',
|
|
23
|
+
'delivery:covid19',
|
|
24
|
+
'safety:mask:covid19',
|
|
25
|
+
];
|
package/config/features.js
CHANGED
|
@@ -2,52 +2,60 @@
|
|
|
2
2
|
/**
|
|
3
3
|
default list of tags to extract from the pbf file when running
|
|
4
4
|
imports. @see: https://github.com/pelias/pbf2json for more info.
|
|
5
|
-
**/
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
'addr:housenumber+addr:place' // @ref https://github.com/pelias/pelias/issues/787#issuecomment-477137803
|
|
11
|
-
];
|
|
6
|
+
addressTags: extracted so address_extractor can assign the address layer downstream.
|
|
7
|
+
these are not a layer themselves — address classification is structural,
|
|
8
|
+
not tag-based.
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
'building+name',
|
|
17
|
-
'shop+name',
|
|
18
|
-
'office+name',
|
|
19
|
-
'public_transport+name',
|
|
20
|
-
'cuisine+name',
|
|
21
|
-
'railway~station+name',
|
|
22
|
-
'railway~tram_stop+name',
|
|
23
|
-
'railway~halt+name',
|
|
24
|
-
'railway~subway_entrance+name',
|
|
25
|
-
'railway~train_station_entrance+name',
|
|
26
|
-
'highway~pedestrian+area~yes+name',
|
|
27
|
-
'place~square+name',
|
|
28
|
-
'sport+name',
|
|
29
|
-
'natural+name',
|
|
30
|
-
'tourism+name',
|
|
31
|
-
'leisure+name',
|
|
32
|
-
'historic+name',
|
|
33
|
-
'man_made+name',
|
|
34
|
-
'landuse+name',
|
|
35
|
-
'waterway+name',
|
|
36
|
-
'aerialway+name',
|
|
37
|
-
'craft+name',
|
|
38
|
-
'military+name',
|
|
39
|
-
'aeroway~terminal+name',
|
|
40
|
-
'aeroway~aerodrome+name',
|
|
41
|
-
'aeroway~helipad+name',
|
|
42
|
-
'aeroway~airstrip+name',
|
|
43
|
-
'aeroway~heliport+name',
|
|
44
|
-
'aeroway~areodrome+name',
|
|
45
|
-
'aeroway~spaceport+name',
|
|
46
|
-
'aeroway~landing_strip+name',
|
|
47
|
-
'aeroway~airfield+name',
|
|
48
|
-
'aeroway~airport+name',
|
|
49
|
-
'brand+name',
|
|
50
|
-
'healthcare+name'
|
|
51
|
-
];
|
|
10
|
+
layers: keyed by output layer name. order determines classifier priority (first match wins).
|
|
11
|
+
add custom layers here (e.g. river, protected_area) to extend the importer.
|
|
12
|
+
**/
|
|
52
13
|
|
|
53
|
-
module.exports = {
|
|
14
|
+
module.exports = {
|
|
15
|
+
addressTags: [
|
|
16
|
+
'addr:housenumber+addr:street',
|
|
17
|
+
'addr:housenumber+addr:place' // @ref https://github.com/pelias/pelias/issues/787#issuecomment-477137803
|
|
18
|
+
],
|
|
19
|
+
layers: {
|
|
20
|
+
venue: {
|
|
21
|
+
tags: [
|
|
22
|
+
'amenity+name',
|
|
23
|
+
'building+name',
|
|
24
|
+
'shop+name',
|
|
25
|
+
'office+name',
|
|
26
|
+
'public_transport+name',
|
|
27
|
+
'cuisine+name',
|
|
28
|
+
'railway~station+name',
|
|
29
|
+
'railway~tram_stop+name',
|
|
30
|
+
'railway~halt+name',
|
|
31
|
+
'railway~subway_entrance+name',
|
|
32
|
+
'railway~train_station_entrance+name',
|
|
33
|
+
'highway~pedestrian+area~yes+name',
|
|
34
|
+
'place~square+name',
|
|
35
|
+
'sport+name',
|
|
36
|
+
'natural+name',
|
|
37
|
+
'tourism+name',
|
|
38
|
+
'leisure+name',
|
|
39
|
+
'historic+name',
|
|
40
|
+
'man_made+name',
|
|
41
|
+
'landuse+name',
|
|
42
|
+
'waterway+name',
|
|
43
|
+
'aerialway+name',
|
|
44
|
+
'craft+name',
|
|
45
|
+
'military+name',
|
|
46
|
+
'aeroway~terminal+name',
|
|
47
|
+
'aeroway~aerodrome+name',
|
|
48
|
+
'aeroway~helipad+name',
|
|
49
|
+
'aeroway~airstrip+name',
|
|
50
|
+
'aeroway~heliport+name',
|
|
51
|
+
'aeroway~areodrome+name',
|
|
52
|
+
'aeroway~spaceport+name',
|
|
53
|
+
'aeroway~landing_strip+name',
|
|
54
|
+
'aeroway~airfield+name',
|
|
55
|
+
'aeroway~airport+name',
|
|
56
|
+
'brand+name',
|
|
57
|
+
'healthcare+name'
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pelias-openstreetmap",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.4.0",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=10.0.0"
|
|
6
6
|
},
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
"end-to-end": "export NODE_ENV=test && node test/end-to-end.js;",
|
|
16
16
|
"lint": "jshint .",
|
|
17
17
|
"start": "./bin/start",
|
|
18
|
+
"taginfo": "node scripts/generate_taginfo.js",
|
|
19
|
+
"prepublishOnly": "npm run taginfo",
|
|
18
20
|
"test": "npm run units",
|
|
19
21
|
"ci": "node ./test/ci-config.js && npm test && npm run end-to-end",
|
|
20
22
|
"units": "./bin/test",
|
package/schema.js
CHANGED
|
@@ -21,7 +21,14 @@ module.exports = Joi.object().keys({
|
|
|
21
21
|
download: Joi.array().items(Joi.object().keys({
|
|
22
22
|
sourceURL: Joi.string()
|
|
23
23
|
}).requiredKeys('sourceURL').unknown(true)),
|
|
24
|
-
deduplicate: Joi.boolean()
|
|
24
|
+
deduplicate: Joi.boolean(),
|
|
25
|
+
addressTags: Joi.array().items(Joi.string()),
|
|
26
|
+
layers: Joi.object().pattern(
|
|
27
|
+
Joi.string(),
|
|
28
|
+
Joi.object().keys({
|
|
29
|
+
tags: Joi.array().items(Joi.string())
|
|
30
|
+
})
|
|
31
|
+
)
|
|
25
32
|
}).requiredKeys('datapath', 'leveldbpath', 'import').unknown(true)
|
|
26
33
|
}).requiredKeys('openstreetmap').unknown(true)
|
|
27
34
|
}).requiredKeys('imports').unknown(true);
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Generates taginfo.json describing which OSM tags Pelias reads.
|
|
6
|
+
*
|
|
7
|
+
* Sources of truth pulled in at generation time:
|
|
8
|
+
* - config/features.js (venue detection tags, address filter keys)
|
|
9
|
+
* - config/addendum_whitelist.js (metadata tags stored in the OSM addendum)
|
|
10
|
+
* - schema/name_osm.js (name/alias tags)
|
|
11
|
+
* - schema/address_*.js (address tags)
|
|
12
|
+
*
|
|
13
|
+
* Published to npm and served by jsDelivr:
|
|
14
|
+
* https://cdn.jsdelivr.net/npm/pelias-openstreetmap/taginfo.json
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const fs = require('fs');
|
|
18
|
+
const path = require('path');
|
|
19
|
+
|
|
20
|
+
const pkg = require('../package.json');
|
|
21
|
+
const features = require('../config/features');
|
|
22
|
+
const nameSchema = require('../schema/name_osm');
|
|
23
|
+
const karlsruhe = require('../schema/address_karlsruhe');
|
|
24
|
+
const osmAddr = require('../schema/address_osm');
|
|
25
|
+
const tiger = require('../schema/address_tiger');
|
|
26
|
+
const naptan = require('../schema/address_naptan');
|
|
27
|
+
const addendumKeys = require('../config/addendum_whitelist');
|
|
28
|
+
|
|
29
|
+
const OBJECT_TYPES = ['node', 'way', 'relation'];
|
|
30
|
+
|
|
31
|
+
function entry(key, description, value) {
|
|
32
|
+
const e = { key };
|
|
33
|
+
if (value !== undefined) {
|
|
34
|
+
e.value = value;
|
|
35
|
+
}
|
|
36
|
+
e.object_types = OBJECT_TYPES;
|
|
37
|
+
e.description = description;
|
|
38
|
+
return e;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// Venue detection tags — derived from config/features.js
|
|
43
|
+
// Format: 'amenity+name', 'railway~station+name', 'highway~pedestrian+area~yes+name'
|
|
44
|
+
// '+' = AND conditions; '~' = key=value; 'name' and 'area~yes' are secondary filters
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
function parseVenueTags(patterns) {
|
|
47
|
+
const seen = new Set();
|
|
48
|
+
const entries = [];
|
|
49
|
+
for (const pattern of patterns) {
|
|
50
|
+
const parts = pattern.split('+').filter(p => p !== 'name' && p !== 'area~yes');
|
|
51
|
+
for (const part of parts) {
|
|
52
|
+
const [key, value] = part.split('~');
|
|
53
|
+
const id = value ? `${key}=${value}` : key;
|
|
54
|
+
if (!seen.has(id)) {
|
|
55
|
+
seen.add(id);
|
|
56
|
+
entries.push({ key, value });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return entries;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const venueTags = parseVenueTags(features.layers.venue.tags).map(({ key, value }) => {
|
|
64
|
+
const desc = value ?
|
|
65
|
+
`${key}=${value} features with a name are imported as venues` :
|
|
66
|
+
`Features with any ${key} tag and a name are imported as venues`;
|
|
67
|
+
return entry(key, desc, value);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
// Address tags — derived from all address schemas + features.addressTags
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
const addressDescriptions = {
|
|
74
|
+
'addr:housenumber': 'House number; required (with addr:street or addr:place) to create an address record',
|
|
75
|
+
'addr:street': 'Street name for address records',
|
|
76
|
+
'addr:place': 'Named settlement used instead of a street for rural addresses',
|
|
77
|
+
'addr:housename': 'Building or house name, imported as the address name',
|
|
78
|
+
'addr:postcode': 'Postal/ZIP code',
|
|
79
|
+
'postal_code': 'Postal code (OSM standard key, alternative to addr:postcode)',
|
|
80
|
+
'tiger:zip_left': 'US TIGER-imported postal code for the left side of the street',
|
|
81
|
+
'tiger:zip_right': 'US TIGER-imported postal code for the right side of the street',
|
|
82
|
+
'naptan:Street': 'Street name from the UK NaPTAN bus stop dataset',
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const addressKeys = new Set([
|
|
86
|
+
...Object.keys(karlsruhe),
|
|
87
|
+
...Object.keys(osmAddr),
|
|
88
|
+
...Object.keys(tiger),
|
|
89
|
+
...Object.keys(naptan),
|
|
90
|
+
// pbf2json filter patterns like 'addr:housenumber+addr:street'
|
|
91
|
+
...features.addressTags.flatMap(p => p.split('+')),
|
|
92
|
+
]);
|
|
93
|
+
|
|
94
|
+
const addressTags = [...addressKeys].map(k =>
|
|
95
|
+
entry(k, addressDescriptions[k] || 'Address field used by the Pelias OSM importer')
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
// Name tags — derived from schema/name_osm.js
|
|
100
|
+
// Localized name tags (name:en, name:fr, …) are read dynamically via iso-639-3
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
const nameDescriptions = {
|
|
103
|
+
name: 'Primary display name; the main search term for a record',
|
|
104
|
+
loc_name: 'Local name; indexed as an alias',
|
|
105
|
+
alt_name: 'Alternative name; indexed as an alias',
|
|
106
|
+
short_name: 'Short name; indexed as an alias',
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const nameTags = [
|
|
110
|
+
...Object.keys(nameSchema).map(k =>
|
|
111
|
+
entry(k, nameDescriptions[k] || 'Name variant indexed as an alias')
|
|
112
|
+
),
|
|
113
|
+
// Localised names are resolved at import time from iso-639-3 (e.g. name:en, name:fr)
|
|
114
|
+
entry('name:*', 'Language-specific names (e.g. name:en, name:fr) are indexed as localized aliases'),
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
// Addendum / metadata tags — derived from config/addendum_whitelist.js
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
const addendumTags = addendumKeys.map(k =>
|
|
121
|
+
entry(k, `${k} is stored verbatim in the OSM addendum of every imported record`)
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
// Assemble, deduplicate (venue tags take precedence), and write
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
const seen = new Set();
|
|
128
|
+
const tags = [...venueTags, ...addressTags, ...nameTags, ...addendumTags].filter(t => {
|
|
129
|
+
const id = t.value !== undefined ? `${t.key}=${t.value}` : t.key;
|
|
130
|
+
if (seen.has(id)) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
seen.add(id);
|
|
134
|
+
return true;
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const output = {
|
|
138
|
+
data_format: 1,
|
|
139
|
+
data_url: `https://cdn.jsdelivr.net/npm/${pkg.name}/taginfo.json`,
|
|
140
|
+
project: {
|
|
141
|
+
name: 'Pelias Geocoder — OpenStreetMap importer',
|
|
142
|
+
description: 'Imports OpenStreetMap data into the Pelias geocoding engine',
|
|
143
|
+
project_url: pkg.homepage,
|
|
144
|
+
doc_url: `${pkg.homepage}#readme`,
|
|
145
|
+
icon_url: 'https://github.com/pelias.png',
|
|
146
|
+
contact_name: 'Pelias Team',
|
|
147
|
+
contact_email: 'team@pelias.io',
|
|
148
|
+
},
|
|
149
|
+
tags,
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const outPath = path.join(__dirname, '..', 'taginfo.json');
|
|
153
|
+
fs.writeFileSync(outPath, JSON.stringify(output, null, 2) + '\n');
|
|
154
|
+
console.log(`taginfo.json written (${tags.length} tag entries)`);
|
|
@@ -7,23 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
const through = require('through2');
|
|
9
9
|
const peliasLogger = require('pelias-logger').get('openstreetmap');
|
|
10
|
-
const whitelist =
|
|
11
|
-
'wheelchair', // Wheelchair accessibility
|
|
12
|
-
'iata', // IATA airport codes
|
|
13
|
-
'icao', // ICAO airport codes
|
|
14
|
-
'wikidata', // Wikidata concordance
|
|
15
|
-
'wikipedia', // Wikipedia concordance
|
|
16
|
-
'operator', // Operator name
|
|
17
|
-
'brand', // Brand name
|
|
18
|
-
'website', // Website URL
|
|
19
|
-
'phone', // Telephone number
|
|
20
|
-
'opening_hours', // Opening hours
|
|
21
|
-
|
|
22
|
-
// COVID-19
|
|
23
|
-
'opening_hours:covid19',
|
|
24
|
-
'delivery:covid19',
|
|
25
|
-
'safety:mask:covid19'
|
|
26
|
-
];
|
|
10
|
+
const whitelist = require('../config/addendum_whitelist');
|
|
27
11
|
|
|
28
12
|
module.exports = function(){
|
|
29
13
|
|
|
@@ -8,6 +8,11 @@ const through = require('through2');
|
|
|
8
8
|
const Document = require('pelias-model').Document;
|
|
9
9
|
const peliasLogger = require( 'pelias-logger' ).get( 'openstreetmap' );
|
|
10
10
|
const _ = require('lodash');
|
|
11
|
+
const settings = require('pelias-config').generate(require('../schema'));
|
|
12
|
+
const resolveFeatures = require('../util/resolveFeatures');
|
|
13
|
+
const { classify } = require('../util/layerClassifier');
|
|
14
|
+
|
|
15
|
+
const { layers } = resolveFeatures(settings);
|
|
11
16
|
|
|
12
17
|
module.exports = function(){
|
|
13
18
|
|
|
@@ -19,8 +24,10 @@ module.exports = function(){
|
|
|
19
24
|
}
|
|
20
25
|
var uniqueId = [ item.type, item.id ].join('/');
|
|
21
26
|
|
|
22
|
-
//
|
|
23
|
-
|
|
27
|
+
// classify the layer from OSM tags; address_extractor assigns the address
|
|
28
|
+
// layer downstream — the classifier only covers named layers (venue, etc.)
|
|
29
|
+
var layer = classify(item.tags || {}, layers);
|
|
30
|
+
var doc = new Document( 'openstreetmap', layer, uniqueId );
|
|
24
31
|
|
|
25
32
|
// Set latitude / longitude
|
|
26
33
|
if( item.hasOwnProperty('lat') && item.hasOwnProperty('lon') ){
|
package/stream/importPipeline.js
CHANGED
|
@@ -13,6 +13,7 @@ streams.tagMapper = require('./tag_mapper');
|
|
|
13
13
|
streams.addressesWithoutStreet = require('./addresses_without_street');
|
|
14
14
|
streams.adminLookup = require('pelias-wof-admin-lookup').create;
|
|
15
15
|
streams.addressExtractor = require('./address_extractor');
|
|
16
|
+
streams.venueFilter = require('./venueFilter');
|
|
16
17
|
streams.categoryMapper = require('./category_mapper');
|
|
17
18
|
streams.addendumMapper = require('./addendum_mapper');
|
|
18
19
|
streams.popularityMapper = require('./popularity_mapper');
|
|
@@ -26,6 +27,7 @@ streams.import = function(){
|
|
|
26
27
|
.pipe( streams.addressesWithoutStreet() )
|
|
27
28
|
.pipe( streams.tagMapper() )
|
|
28
29
|
.pipe( streams.addressExtractor() )
|
|
30
|
+
.pipe( streams.venueFilter() )
|
|
29
31
|
.pipe( streams.blacklistStream() )
|
|
30
32
|
.pipe( streams.categoryMapper( categoryDefaults ) )
|
|
31
33
|
.pipe( streams.addendumMapper() )
|
package/stream/pbf.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
var fs = require('fs'),
|
|
8
8
|
pbf2json = require('pbf2json'),
|
|
9
9
|
settings = require('pelias-config').generate(require('../schema')),
|
|
10
|
-
|
|
10
|
+
resolveFeatures = require('../util/resolveFeatures'),
|
|
11
11
|
path = require('path');
|
|
12
12
|
|
|
13
13
|
// Create a new pbf parser stream
|
|
@@ -46,11 +46,11 @@ function config(opts){
|
|
|
46
46
|
if(!opts.tags){
|
|
47
47
|
// check if we import venues
|
|
48
48
|
opts.importVenues = settings.imports.openstreetmap.import[0].importVenues;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
const features = resolveFeatures(settings);
|
|
50
|
+
const layerTags = opts.importVenues === false ?
|
|
51
|
+
[] :
|
|
52
|
+
Object.values(features.layers).flatMap(l => l.tags ?? []);
|
|
53
|
+
opts.tags = features.addressTags.concat(layerTags);
|
|
54
54
|
}
|
|
55
55
|
return opts;
|
|
56
56
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* When importVenues is false, drop any record that is not in the address layer.
|
|
5
|
+
* This prevents named POIs that also have address tags from leaking through as
|
|
6
|
+
* venue records when venue import is disabled.
|
|
7
|
+
*
|
|
8
|
+
* Note: the preferred way to control which layers are imported is now to set
|
|
9
|
+
* `imports.openstreetmap.layers` in pelias.json. Setting `importVenues: false`
|
|
10
|
+
* is equivalent to `layers: {}` and is retained for backward compatibility.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const through = require('through2');
|
|
14
|
+
const settings = require('pelias-config').generate(require('../schema'));
|
|
15
|
+
|
|
16
|
+
module.exports = function() {
|
|
17
|
+
const importVenues = settings.imports.openstreetmap.import[0].importVenues;
|
|
18
|
+
|
|
19
|
+
// passthrough when venues are enabled (default)
|
|
20
|
+
if (importVenues !== false) {
|
|
21
|
+
return through.obj();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return through.obj(function(doc, enc, next) {
|
|
25
|
+
if (doc.getLayer() === 'address') {
|
|
26
|
+
this.push(doc);
|
|
27
|
+
}
|
|
28
|
+
next();
|
|
29
|
+
});
|
|
30
|
+
};
|
package/taginfo.json
ADDED
|
@@ -0,0 +1,590 @@
|
|
|
1
|
+
{
|
|
2
|
+
"data_format": 1,
|
|
3
|
+
"data_url": "https://cdn.jsdelivr.net/npm/pelias-openstreetmap/taginfo.json",
|
|
4
|
+
"project": {
|
|
5
|
+
"name": "Pelias Geocoder — OpenStreetMap importer",
|
|
6
|
+
"description": "Imports OpenStreetMap data into the Pelias geocoding engine",
|
|
7
|
+
"project_url": "https://github.com/pelias/openstreetmap",
|
|
8
|
+
"doc_url": "https://github.com/pelias/openstreetmap#readme",
|
|
9
|
+
"icon_url": "https://github.com/pelias.png",
|
|
10
|
+
"contact_name": "Pelias Team",
|
|
11
|
+
"contact_email": "team@pelias.io"
|
|
12
|
+
},
|
|
13
|
+
"tags": [
|
|
14
|
+
{
|
|
15
|
+
"key": "amenity",
|
|
16
|
+
"object_types": [
|
|
17
|
+
"node",
|
|
18
|
+
"way",
|
|
19
|
+
"relation"
|
|
20
|
+
],
|
|
21
|
+
"description": "Features with any amenity tag and a name are imported as venues"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"key": "building",
|
|
25
|
+
"object_types": [
|
|
26
|
+
"node",
|
|
27
|
+
"way",
|
|
28
|
+
"relation"
|
|
29
|
+
],
|
|
30
|
+
"description": "Features with any building tag and a name are imported as venues"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"key": "shop",
|
|
34
|
+
"object_types": [
|
|
35
|
+
"node",
|
|
36
|
+
"way",
|
|
37
|
+
"relation"
|
|
38
|
+
],
|
|
39
|
+
"description": "Features with any shop tag and a name are imported as venues"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"key": "office",
|
|
43
|
+
"object_types": [
|
|
44
|
+
"node",
|
|
45
|
+
"way",
|
|
46
|
+
"relation"
|
|
47
|
+
],
|
|
48
|
+
"description": "Features with any office tag and a name are imported as venues"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"key": "public_transport",
|
|
52
|
+
"object_types": [
|
|
53
|
+
"node",
|
|
54
|
+
"way",
|
|
55
|
+
"relation"
|
|
56
|
+
],
|
|
57
|
+
"description": "Features with any public_transport tag and a name are imported as venues"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"key": "cuisine",
|
|
61
|
+
"object_types": [
|
|
62
|
+
"node",
|
|
63
|
+
"way",
|
|
64
|
+
"relation"
|
|
65
|
+
],
|
|
66
|
+
"description": "Features with any cuisine tag and a name are imported as venues"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"key": "railway",
|
|
70
|
+
"value": "station",
|
|
71
|
+
"object_types": [
|
|
72
|
+
"node",
|
|
73
|
+
"way",
|
|
74
|
+
"relation"
|
|
75
|
+
],
|
|
76
|
+
"description": "railway=station features with a name are imported as venues"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"key": "railway",
|
|
80
|
+
"value": "tram_stop",
|
|
81
|
+
"object_types": [
|
|
82
|
+
"node",
|
|
83
|
+
"way",
|
|
84
|
+
"relation"
|
|
85
|
+
],
|
|
86
|
+
"description": "railway=tram_stop features with a name are imported as venues"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"key": "railway",
|
|
90
|
+
"value": "halt",
|
|
91
|
+
"object_types": [
|
|
92
|
+
"node",
|
|
93
|
+
"way",
|
|
94
|
+
"relation"
|
|
95
|
+
],
|
|
96
|
+
"description": "railway=halt features with a name are imported as venues"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"key": "railway",
|
|
100
|
+
"value": "subway_entrance",
|
|
101
|
+
"object_types": [
|
|
102
|
+
"node",
|
|
103
|
+
"way",
|
|
104
|
+
"relation"
|
|
105
|
+
],
|
|
106
|
+
"description": "railway=subway_entrance features with a name are imported as venues"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"key": "railway",
|
|
110
|
+
"value": "train_station_entrance",
|
|
111
|
+
"object_types": [
|
|
112
|
+
"node",
|
|
113
|
+
"way",
|
|
114
|
+
"relation"
|
|
115
|
+
],
|
|
116
|
+
"description": "railway=train_station_entrance features with a name are imported as venues"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"key": "highway",
|
|
120
|
+
"value": "pedestrian",
|
|
121
|
+
"object_types": [
|
|
122
|
+
"node",
|
|
123
|
+
"way",
|
|
124
|
+
"relation"
|
|
125
|
+
],
|
|
126
|
+
"description": "highway=pedestrian features with a name are imported as venues"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"key": "place",
|
|
130
|
+
"value": "square",
|
|
131
|
+
"object_types": [
|
|
132
|
+
"node",
|
|
133
|
+
"way",
|
|
134
|
+
"relation"
|
|
135
|
+
],
|
|
136
|
+
"description": "place=square features with a name are imported as venues"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"key": "sport",
|
|
140
|
+
"object_types": [
|
|
141
|
+
"node",
|
|
142
|
+
"way",
|
|
143
|
+
"relation"
|
|
144
|
+
],
|
|
145
|
+
"description": "Features with any sport tag and a name are imported as venues"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"key": "natural",
|
|
149
|
+
"object_types": [
|
|
150
|
+
"node",
|
|
151
|
+
"way",
|
|
152
|
+
"relation"
|
|
153
|
+
],
|
|
154
|
+
"description": "Features with any natural tag and a name are imported as venues"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"key": "tourism",
|
|
158
|
+
"object_types": [
|
|
159
|
+
"node",
|
|
160
|
+
"way",
|
|
161
|
+
"relation"
|
|
162
|
+
],
|
|
163
|
+
"description": "Features with any tourism tag and a name are imported as venues"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"key": "leisure",
|
|
167
|
+
"object_types": [
|
|
168
|
+
"node",
|
|
169
|
+
"way",
|
|
170
|
+
"relation"
|
|
171
|
+
],
|
|
172
|
+
"description": "Features with any leisure tag and a name are imported as venues"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"key": "historic",
|
|
176
|
+
"object_types": [
|
|
177
|
+
"node",
|
|
178
|
+
"way",
|
|
179
|
+
"relation"
|
|
180
|
+
],
|
|
181
|
+
"description": "Features with any historic tag and a name are imported as venues"
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"key": "man_made",
|
|
185
|
+
"object_types": [
|
|
186
|
+
"node",
|
|
187
|
+
"way",
|
|
188
|
+
"relation"
|
|
189
|
+
],
|
|
190
|
+
"description": "Features with any man_made tag and a name are imported as venues"
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
"key": "landuse",
|
|
194
|
+
"object_types": [
|
|
195
|
+
"node",
|
|
196
|
+
"way",
|
|
197
|
+
"relation"
|
|
198
|
+
],
|
|
199
|
+
"description": "Features with any landuse tag and a name are imported as venues"
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"key": "waterway",
|
|
203
|
+
"object_types": [
|
|
204
|
+
"node",
|
|
205
|
+
"way",
|
|
206
|
+
"relation"
|
|
207
|
+
],
|
|
208
|
+
"description": "Features with any waterway tag and a name are imported as venues"
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
"key": "aerialway",
|
|
212
|
+
"object_types": [
|
|
213
|
+
"node",
|
|
214
|
+
"way",
|
|
215
|
+
"relation"
|
|
216
|
+
],
|
|
217
|
+
"description": "Features with any aerialway tag and a name are imported as venues"
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"key": "craft",
|
|
221
|
+
"object_types": [
|
|
222
|
+
"node",
|
|
223
|
+
"way",
|
|
224
|
+
"relation"
|
|
225
|
+
],
|
|
226
|
+
"description": "Features with any craft tag and a name are imported as venues"
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"key": "military",
|
|
230
|
+
"object_types": [
|
|
231
|
+
"node",
|
|
232
|
+
"way",
|
|
233
|
+
"relation"
|
|
234
|
+
],
|
|
235
|
+
"description": "Features with any military tag and a name are imported as venues"
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"key": "aeroway",
|
|
239
|
+
"value": "terminal",
|
|
240
|
+
"object_types": [
|
|
241
|
+
"node",
|
|
242
|
+
"way",
|
|
243
|
+
"relation"
|
|
244
|
+
],
|
|
245
|
+
"description": "aeroway=terminal features with a name are imported as venues"
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"key": "aeroway",
|
|
249
|
+
"value": "aerodrome",
|
|
250
|
+
"object_types": [
|
|
251
|
+
"node",
|
|
252
|
+
"way",
|
|
253
|
+
"relation"
|
|
254
|
+
],
|
|
255
|
+
"description": "aeroway=aerodrome features with a name are imported as venues"
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"key": "aeroway",
|
|
259
|
+
"value": "helipad",
|
|
260
|
+
"object_types": [
|
|
261
|
+
"node",
|
|
262
|
+
"way",
|
|
263
|
+
"relation"
|
|
264
|
+
],
|
|
265
|
+
"description": "aeroway=helipad features with a name are imported as venues"
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"key": "aeroway",
|
|
269
|
+
"value": "airstrip",
|
|
270
|
+
"object_types": [
|
|
271
|
+
"node",
|
|
272
|
+
"way",
|
|
273
|
+
"relation"
|
|
274
|
+
],
|
|
275
|
+
"description": "aeroway=airstrip features with a name are imported as venues"
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
"key": "aeroway",
|
|
279
|
+
"value": "heliport",
|
|
280
|
+
"object_types": [
|
|
281
|
+
"node",
|
|
282
|
+
"way",
|
|
283
|
+
"relation"
|
|
284
|
+
],
|
|
285
|
+
"description": "aeroway=heliport features with a name are imported as venues"
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
"key": "aeroway",
|
|
289
|
+
"value": "areodrome",
|
|
290
|
+
"object_types": [
|
|
291
|
+
"node",
|
|
292
|
+
"way",
|
|
293
|
+
"relation"
|
|
294
|
+
],
|
|
295
|
+
"description": "aeroway=areodrome features with a name are imported as venues"
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"key": "aeroway",
|
|
299
|
+
"value": "spaceport",
|
|
300
|
+
"object_types": [
|
|
301
|
+
"node",
|
|
302
|
+
"way",
|
|
303
|
+
"relation"
|
|
304
|
+
],
|
|
305
|
+
"description": "aeroway=spaceport features with a name are imported as venues"
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
"key": "aeroway",
|
|
309
|
+
"value": "landing_strip",
|
|
310
|
+
"object_types": [
|
|
311
|
+
"node",
|
|
312
|
+
"way",
|
|
313
|
+
"relation"
|
|
314
|
+
],
|
|
315
|
+
"description": "aeroway=landing_strip features with a name are imported as venues"
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
"key": "aeroway",
|
|
319
|
+
"value": "airfield",
|
|
320
|
+
"object_types": [
|
|
321
|
+
"node",
|
|
322
|
+
"way",
|
|
323
|
+
"relation"
|
|
324
|
+
],
|
|
325
|
+
"description": "aeroway=airfield features with a name are imported as venues"
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
"key": "aeroway",
|
|
329
|
+
"value": "airport",
|
|
330
|
+
"object_types": [
|
|
331
|
+
"node",
|
|
332
|
+
"way",
|
|
333
|
+
"relation"
|
|
334
|
+
],
|
|
335
|
+
"description": "aeroway=airport features with a name are imported as venues"
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
"key": "brand",
|
|
339
|
+
"object_types": [
|
|
340
|
+
"node",
|
|
341
|
+
"way",
|
|
342
|
+
"relation"
|
|
343
|
+
],
|
|
344
|
+
"description": "Features with any brand tag and a name are imported as venues"
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
"key": "healthcare",
|
|
348
|
+
"object_types": [
|
|
349
|
+
"node",
|
|
350
|
+
"way",
|
|
351
|
+
"relation"
|
|
352
|
+
],
|
|
353
|
+
"description": "Features with any healthcare tag and a name are imported as venues"
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
"key": "addr:housename",
|
|
357
|
+
"object_types": [
|
|
358
|
+
"node",
|
|
359
|
+
"way",
|
|
360
|
+
"relation"
|
|
361
|
+
],
|
|
362
|
+
"description": "Building or house name, imported as the address name"
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
"key": "addr:housenumber",
|
|
366
|
+
"object_types": [
|
|
367
|
+
"node",
|
|
368
|
+
"way",
|
|
369
|
+
"relation"
|
|
370
|
+
],
|
|
371
|
+
"description": "House number; required (with addr:street or addr:place) to create an address record"
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
"key": "addr:street",
|
|
375
|
+
"object_types": [
|
|
376
|
+
"node",
|
|
377
|
+
"way",
|
|
378
|
+
"relation"
|
|
379
|
+
],
|
|
380
|
+
"description": "Street name for address records"
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
"key": "addr:postcode",
|
|
384
|
+
"object_types": [
|
|
385
|
+
"node",
|
|
386
|
+
"way",
|
|
387
|
+
"relation"
|
|
388
|
+
],
|
|
389
|
+
"description": "Postal/ZIP code"
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
"key": "postal_code",
|
|
393
|
+
"object_types": [
|
|
394
|
+
"node",
|
|
395
|
+
"way",
|
|
396
|
+
"relation"
|
|
397
|
+
],
|
|
398
|
+
"description": "Postal code (OSM standard key, alternative to addr:postcode)"
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
"key": "tiger:zip_left",
|
|
402
|
+
"object_types": [
|
|
403
|
+
"node",
|
|
404
|
+
"way",
|
|
405
|
+
"relation"
|
|
406
|
+
],
|
|
407
|
+
"description": "US TIGER-imported postal code for the left side of the street"
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
"key": "tiger:zip_right",
|
|
411
|
+
"object_types": [
|
|
412
|
+
"node",
|
|
413
|
+
"way",
|
|
414
|
+
"relation"
|
|
415
|
+
],
|
|
416
|
+
"description": "US TIGER-imported postal code for the right side of the street"
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
"key": "naptan:Street",
|
|
420
|
+
"object_types": [
|
|
421
|
+
"node",
|
|
422
|
+
"way",
|
|
423
|
+
"relation"
|
|
424
|
+
],
|
|
425
|
+
"description": "Street name from the UK NaPTAN bus stop dataset"
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
"key": "addr:place",
|
|
429
|
+
"object_types": [
|
|
430
|
+
"node",
|
|
431
|
+
"way",
|
|
432
|
+
"relation"
|
|
433
|
+
],
|
|
434
|
+
"description": "Named settlement used instead of a street for rural addresses"
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
"key": "name",
|
|
438
|
+
"object_types": [
|
|
439
|
+
"node",
|
|
440
|
+
"way",
|
|
441
|
+
"relation"
|
|
442
|
+
],
|
|
443
|
+
"description": "Primary display name; the main search term for a record"
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
"key": "loc_name",
|
|
447
|
+
"object_types": [
|
|
448
|
+
"node",
|
|
449
|
+
"way",
|
|
450
|
+
"relation"
|
|
451
|
+
],
|
|
452
|
+
"description": "Local name; indexed as an alias"
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
"key": "alt_name",
|
|
456
|
+
"object_types": [
|
|
457
|
+
"node",
|
|
458
|
+
"way",
|
|
459
|
+
"relation"
|
|
460
|
+
],
|
|
461
|
+
"description": "Alternative name; indexed as an alias"
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
"key": "short_name",
|
|
465
|
+
"object_types": [
|
|
466
|
+
"node",
|
|
467
|
+
"way",
|
|
468
|
+
"relation"
|
|
469
|
+
],
|
|
470
|
+
"description": "Short name; indexed as an alias"
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
"key": "name:*",
|
|
474
|
+
"object_types": [
|
|
475
|
+
"node",
|
|
476
|
+
"way",
|
|
477
|
+
"relation"
|
|
478
|
+
],
|
|
479
|
+
"description": "Language-specific names (e.g. name:en, name:fr) are indexed as localized aliases"
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
"key": "wheelchair",
|
|
483
|
+
"object_types": [
|
|
484
|
+
"node",
|
|
485
|
+
"way",
|
|
486
|
+
"relation"
|
|
487
|
+
],
|
|
488
|
+
"description": "wheelchair is stored verbatim in the OSM addendum of every imported record"
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
"key": "iata",
|
|
492
|
+
"object_types": [
|
|
493
|
+
"node",
|
|
494
|
+
"way",
|
|
495
|
+
"relation"
|
|
496
|
+
],
|
|
497
|
+
"description": "iata is stored verbatim in the OSM addendum of every imported record"
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
"key": "icao",
|
|
501
|
+
"object_types": [
|
|
502
|
+
"node",
|
|
503
|
+
"way",
|
|
504
|
+
"relation"
|
|
505
|
+
],
|
|
506
|
+
"description": "icao is stored verbatim in the OSM addendum of every imported record"
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
"key": "wikidata",
|
|
510
|
+
"object_types": [
|
|
511
|
+
"node",
|
|
512
|
+
"way",
|
|
513
|
+
"relation"
|
|
514
|
+
],
|
|
515
|
+
"description": "wikidata is stored verbatim in the OSM addendum of every imported record"
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
"key": "wikipedia",
|
|
519
|
+
"object_types": [
|
|
520
|
+
"node",
|
|
521
|
+
"way",
|
|
522
|
+
"relation"
|
|
523
|
+
],
|
|
524
|
+
"description": "wikipedia is stored verbatim in the OSM addendum of every imported record"
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
"key": "operator",
|
|
528
|
+
"object_types": [
|
|
529
|
+
"node",
|
|
530
|
+
"way",
|
|
531
|
+
"relation"
|
|
532
|
+
],
|
|
533
|
+
"description": "operator is stored verbatim in the OSM addendum of every imported record"
|
|
534
|
+
},
|
|
535
|
+
{
|
|
536
|
+
"key": "website",
|
|
537
|
+
"object_types": [
|
|
538
|
+
"node",
|
|
539
|
+
"way",
|
|
540
|
+
"relation"
|
|
541
|
+
],
|
|
542
|
+
"description": "website is stored verbatim in the OSM addendum of every imported record"
|
|
543
|
+
},
|
|
544
|
+
{
|
|
545
|
+
"key": "phone",
|
|
546
|
+
"object_types": [
|
|
547
|
+
"node",
|
|
548
|
+
"way",
|
|
549
|
+
"relation"
|
|
550
|
+
],
|
|
551
|
+
"description": "phone is stored verbatim in the OSM addendum of every imported record"
|
|
552
|
+
},
|
|
553
|
+
{
|
|
554
|
+
"key": "opening_hours",
|
|
555
|
+
"object_types": [
|
|
556
|
+
"node",
|
|
557
|
+
"way",
|
|
558
|
+
"relation"
|
|
559
|
+
],
|
|
560
|
+
"description": "opening_hours is stored verbatim in the OSM addendum of every imported record"
|
|
561
|
+
},
|
|
562
|
+
{
|
|
563
|
+
"key": "opening_hours:covid19",
|
|
564
|
+
"object_types": [
|
|
565
|
+
"node",
|
|
566
|
+
"way",
|
|
567
|
+
"relation"
|
|
568
|
+
],
|
|
569
|
+
"description": "opening_hours:covid19 is stored verbatim in the OSM addendum of every imported record"
|
|
570
|
+
},
|
|
571
|
+
{
|
|
572
|
+
"key": "delivery:covid19",
|
|
573
|
+
"object_types": [
|
|
574
|
+
"node",
|
|
575
|
+
"way",
|
|
576
|
+
"relation"
|
|
577
|
+
],
|
|
578
|
+
"description": "delivery:covid19 is stored verbatim in the OSM addendum of every imported record"
|
|
579
|
+
},
|
|
580
|
+
{
|
|
581
|
+
"key": "safety:mask:covid19",
|
|
582
|
+
"object_types": [
|
|
583
|
+
"node",
|
|
584
|
+
"way",
|
|
585
|
+
"relation"
|
|
586
|
+
],
|
|
587
|
+
"description": "safety:mask:covid19 is stored verbatim in the OSM addendum of every imported record"
|
|
588
|
+
}
|
|
589
|
+
]
|
|
590
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Test a single pbf2json tag condition against an OSM tags object.
|
|
5
|
+
* Supports 'key' (key must exist) or 'key~value' (key must equal value).
|
|
6
|
+
*/
|
|
7
|
+
function conditionMatchesTags(condition, tags) {
|
|
8
|
+
const tildeIdx = condition.indexOf('~');
|
|
9
|
+
if (tildeIdx === -1) {
|
|
10
|
+
return Object.prototype.hasOwnProperty.call(tags, condition);
|
|
11
|
+
}
|
|
12
|
+
const key = condition.slice(0, tildeIdx);
|
|
13
|
+
const value = condition.slice(tildeIdx + 1);
|
|
14
|
+
return tags[key] === value;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Test whether a full pbf2json pattern string matches a tags object.
|
|
19
|
+
* Pattern conditions are separated by '+' and all must match (AND logic).
|
|
20
|
+
*/
|
|
21
|
+
function patternMatchesTags(pattern, tags) {
|
|
22
|
+
return pattern.split('+').every(cond => conditionMatchesTags(cond, tags));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Classify an OSM tags object against the features config.
|
|
27
|
+
* Iterates layers in declaration order and returns the first matching layer.
|
|
28
|
+
* Falls back to 'venue' if no patterns match.
|
|
29
|
+
*
|
|
30
|
+
* @param {Object} tags - OSM tags from a pbf2json record
|
|
31
|
+
* @param {Object} features - the features.js keyed-by-layer export
|
|
32
|
+
* @returns {string} layer name
|
|
33
|
+
*/
|
|
34
|
+
function classify(tags, features) {
|
|
35
|
+
const matchesTags = p => patternMatchesTags(p, tags);
|
|
36
|
+
for (const [layer, config] of Object.entries(features)) {
|
|
37
|
+
if (Array.isArray(config.tags) && config.tags.some(matchesTags)) {
|
|
38
|
+
return layer;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return 'venue';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = { patternMatchesTags, classify };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const defaults = require('../config/features');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Resolve the effective features config by merging pelias.json overrides
|
|
7
|
+
* with the defaults from config/features.js.
|
|
8
|
+
*
|
|
9
|
+
* If `imports.openstreetmap.layers` is set in pelias.json it fully replaces
|
|
10
|
+
* the default layer set. Same for `addressTags`. This lets operators add
|
|
11
|
+
* custom layers (e.g. protected_area) or restrict which tags are extracted
|
|
12
|
+
* without touching the source code.
|
|
13
|
+
*
|
|
14
|
+
* @param {Object} settings - result of pelias-config generate()
|
|
15
|
+
* @returns {{ addressTags: string[], layers: Object }}
|
|
16
|
+
*/
|
|
17
|
+
function resolveFeatures(settings) {
|
|
18
|
+
const osmConfig = (settings && settings.imports && settings.imports.openstreetmap) || {};
|
|
19
|
+
return {
|
|
20
|
+
addressTags: osmConfig.addressTags || defaults.addressTags,
|
|
21
|
+
layers: osmConfig.layers || defaults.layers
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = resolveFeatures;
|