osm2pgsql supports Lua scripts to rewrite tags before they enter the database.
This allows you to unify disparate tagging (for example, highway=path; foot=yes
and highway=footway
) and perform complex queries, potentially more efficiently than writing them as rules in your Mapnik or other stylesheet.
Pass a Lua script to osm2pgsql using the command line switch --tag-transform-script
:
osm2pgsql -d gis -S your.style --tag-transform-script your.lua --hstore-all extract.osm.pbf
This Lua script needs to implement the following functions:
function filter_tags_node(tags, num_tags)
return filter, tags
function filter_tags_way(tags, num_tags)
return filter, tags, polygon, roads
function filter_basic_tags_rel(tags, num_tags)
return filter, tags
These take a set of tags as a Lua key-value table, and an integer which is the number of tags supplied.
The first return value is filter
, a flag which you should set to 1
if the way/node/relation should be filtered out and not added to the database, 0
otherwise. (They will still end up in the slim mode tables, but not in the rendering tables)
The second return value is tags
, a transformed (or unchanged) set of tags.
filter_tags_way
returns two additional flags. poly
should be 1
if the way should be treated as a polygon, 0
as a line. roads
should be 1
if the way should be added to the planet_osm_roads table, 0
otherwise.
function filter_tags_relation_member(tags, member_tags,
roles, num_members)
return filter, tags, member_superseded, boundary,
polygon, roads
The function filter_tags_relation_member is more complex and can handle more advanced relation tagging, such as multipolygons that take their tags from the member ways.
This function is called with the tags from the relation; an set of tags for each of the member ways (member relations and nodes are ignored); the set of roles for each of the member ways; and the number of members. The tag and role sets are both arrays (indexed tables) of hashes (tables).
As usual, it should return a filter flag, and a transformed set of tags to be applied to the relation in later processing.
The third return value, member_superseded
, is a flag set to 1
if the way has now been dealt with (e.g. outer ways in multipolygon relations, which are superseded by the multipolygon geometry), 0
if it needs to have its own entry in the database (e.g. tagged inner ways).
The fourth and fifth return values, boundary
and polygon
, are flags that specify if the relation should be processed as a line, a polygon, or both (e.g. administrative boundaries).
The final return value, roads
, is 1
if the geometry should be added to the planet_osm_roads
table.
There is a sample tag transform lua script in the repository as an example, which (nearly) replicates current processing and can be used as a template for one's own scripts.
There is inevitably a performance hit with any extra processing. The sample Lua tag transformation is a little slower than the C-based default. However, extensive Lua pre-processing may save you further processing in your Mapnik (or other) stylesheet.
Test your Lua script with small excerpts before applying it to a whole country or even the planet.
Where possible, add new tags, don't replace existing ones; otherwise you will be faced with a reimport if you decide to change your transformation.