drolbr / Overpass-API

A database engine to query the OpenStreetMap data.
http://overpass-api.de
GNU Affero General Public License v3.0
692 stars 90 forks source link

Overpass Query Optimization #647

Closed fotisz closed 2 years ago

fotisz commented 2 years ago

Trying to optimize query below as it won't run for UK, idea is that I attach some information from nearby nodes to the selected nodes (buffer_stops). All ideas welcome, query below:

// data format and time before the query cancels
[out:csv(::id, ::lat, ::lon, railway, station, name, platforms, "ref:crs", crs, "ref:stanox", "ref:tiploc", "naptan:AtcoCode")][timeout:1000];
//[out:json][timeout:1000];
// filter to UK so I can zoom out and not worry about including other countries
area[admin_level=2][name="United Kingdom"]->.a;
(
  node[railway=buffer_stop](area.a)({{bbox}})->.bufferstops;
  node(around.bufferstops:200)[railway="station"]->.bfstations;
  node(area.a)({{bbox}})[railway="buffer_stop"];
  foreach(
    is_in->.a;
    node(around.a:200)[railway="station"]->.a;
    convert node ::=::,
              ::id = id(),
              station=a.set(t["name"]),
              crs=a.set(t["ref:crs"]);
    out;
  );
  node(around.bufferstops:200)[railway="station"]->.bfstations;
 );
out;
mmd-osm commented 2 years ago

Not a good to place to discuss this topic (repo is for bug reports and enhancement requests). Can you describe in more detail what you're trying to achieve here?

Maybe try your query on a really small area instead of UK, until you get some proper results.

fotisz commented 2 years ago

Thanks for the quick response - suggestion to post as a github issue was on here, if there is another place to look please let me know ... query works for a small bounded box as I want, but then it doesn't seem to scale ... re-written it as follows:

// data format and time before the query cancels
//[out:csv(::id, ::lat, ::lon, railway, station, name, platforms, "ref:crs", crs, "ref:stanox", "ref:tiploc", "naptan:AtcoCode")][timeout:1000];
[out:json][timeout:1000];
// filter to area
area[admin_level=4][name="England"]->.a;
(
  node[railway=buffer_stop](area.a)({{bbox}})->.bufferstops;
  node(around.bufferstops:200)[railway="station"]->.bfstations;
  foreach.bufferstops(
    is_in->.a;
    node(around.a:200)[railway="station"]->.a;
    convert node ::=::,
              ::id = id(),
              station=a.set(t["name"]),
              crs=a.set(t["ref:crs"]);
    out;
    );
);
out;

is_in used mostly so that I don't loop n times through all bufferstops. What I am trying to do is to copy on the node bufferstops the information of the neighbouring stations such as station name and crs code ...

All feedback welcome

mmd-osm commented 2 years ago

By using foreach.bufferstops, you would iterate exactly once over all bufferstops, and the node(around...) would identify railway stations close to the buffer stops.

is_in may have some unexpected results, as it includes many unrelated ways and areas, such as in the following example:


(
  node(7832550438);
  is_in;
);  
out geom;

(returns 5 areas, 2 polygons, most of which are unrelated to railways)

I'd propose the following query:

// data format and time before the query cancels
//[out:csv(::id, ::lat, ::lon, railway, station, name, platforms, "ref:crs", crs, "ref:stanox", "ref:tiploc", "naptan:AtcoCode")][timeout:1000];
[out:json][timeout:1000];
// filter to area
 area[admin_level=4][name="England"]->.area;
//area[admin_level=2][name="United Kingdom"]->.area;

node[railway=buffer_stop](area.area)->.bufferstops;
// .bufferstops out;
node(around.bufferstops:200)[railway="station"]->.bfstations;
// .bfstations out;

foreach.bufferstops (
  out;     // debug help to display results on the map in overpass turbo
  node(around:200)[railway="station"]->.bfstation;
  convert node ::=::,
            ::id = id(),
          station=bfstation.set(t["name"]),
              crs=bfstation.set(t["ref:crs"]);
  out;
);
fotisz commented 2 years ago

Thanks a lot!