omniscale / imposm3

Imposm imports OpenStreetMap data into PostGIS
http://imposm.org/docs/imposm3/latest/
Apache License 2.0
708 stars 156 forks source link

Adding specific `AND` filters on tags #273

Open willieCzito opened 3 years ago

willieCzito commented 3 years ago

Context

Here is an idea for improving imposm. I want to be able to apply specific filters to specific tags.

For example, I would like to map all data about oil tanks in one single table. This is how I am currently doing:

{
  "tags": {
    "load_all": true
  },
  "tables": {
    "oil_tank": {
      "type": "geometry",
      "columns": [
        {
          "type": "id",
          "name": "osm_id",
          "key": null
        },
        {
          "type": "geometry",
          "name": "geometry",
          "key": null
        },
        {
          "type": "mapping_value",
          "key": null
        },
        {
          "type": "hstore_tags",
          "name": "other_tags",
          "key": null
        }
      ],
      "filters": {
        "reject": {
          "content": ["water", "wastewater", "sewage", "manure", "hot_water"]
        }
      },
      "type_mappings": {
        "polygons": {
          "man_made": [
            "gasometer",
            "storage_tank"
          ]
        },
        "points": {
          "man_made": [
            "gasometer",
            "storage_tank"
          ]
        }
      }
    }
  }
}

The problem here is about using a reject filter instead of an accept one. So, if a new content tag is added for storage tanks, for something else than oil, then my results will be false. So this solution is not ideal.

On the other hand, if I'm using an accept filter, this will force both rows with {"man_made" : "storage_tank"} and {"man_made" : "gasometer"} to have a content tag corresponding to my list, but for gasometer no such tag exists...

Expected Behavior

What I want is to be able to choose a filter accept for rows having {"man_made" : "storage_tank"} like this: {"content": ["fuel","natural_gas","hydrocarbons", "gas", "LNG", "LPG", "oil"], and no filter on content for {"man_made" : "gasometer"}.

The goal being to be able to aggregate data from both storage tanks and [gasometers](wiki page) in one single table, applying different filters according to some tag value.

Possible Fix

What I imagine is something like the following, but there might be a better way.

{
  "tags": {
    "load_all": true
  },
  "tables": {
    "oil_building": {
      "type": "geometry",
      "columns": [
        {
          "type": "id",
          "name": "osm_id",
          "key": null
        },
        {
          "type": "geometry",
          "name": "geometry",
          "key": null
        },
        {
          "type": "mapping_value",
          "key": null
        },
        {
          "type": "hstore_tags",
          "name": "other_tags",
          "key": null
        }
      ],
      "type_mappings": {
        "polygons": [
          {
            "man_made": "gasometer"
          }, //OR
          {
            "man_made": "storage_tank", // AND
            "content": ["fuel","natural_gas","hydrocarbons", "gas", "LNG", "LPG", "oil"]
          }
        ],
        "points": [
          {
            "man_made": "gasometer"
          }, //OR
          {
            "man_made": "storage_tank", //AND
            "content": ["fuel","natural_gas","hydrocarbons", "gas", "LNG", "LPG", "oil"]
          }
        ]
      }
    }
  }
}

And maybe there's already a way to do this but I couldn't find one in the documentation.

ImreSamu commented 3 years ago

The goal being to be able to aggregate data from both storage tanks and [gasometers](wiki page) in one single table, applying different filters according to some tag value.

my recommendation as a workaround:

see an example: https://github.com/omniscale/imposm3/issues/217#issuecomment-564890568 just replace : "green" --> storage_tank ; "red"--> gasometer