Overpass API User's Manual

Counting Objects
Analysing data
More information

Pipeline Building

How to build pipelines of search criteria to search for objects relative to other objects.

Indirect Filters

We have seen examples of indirect filters in the section about Areas and the section about Around. The filter arrangement profits from the step-by-step paradigm to refer to objects that are not necessarily contained in the visible result.

We demonstrate this with the example to show all cafés in Cologne:

area[name="Köln"];
nwr[amenity=cafe](area);
out center;

At the heart of the request is the filter (area) in line 2. The filter decided what it accepts by the area or areas that are selected in the set _ at that moment. It is applied in combination with the filter [amenity=cafe], i.e. we select in line 2 all objects that are a node, way, or relation and that bear the tag amenity with value cafe and that are situated within at least one of the in _ selected areas.

To make the implicit set _ more visible, we can use any of the following equivalent rephrasings:

area[name="Köln"];
nwr[amenity=cafe](area._);
out center;

and

area[name="Köln"]->._;
nwr[amenity=cafe](area);
out center;

and

area[name="Köln"]->._;
nwr[amenity=cafe](area._);
out center;

In all cases the area is conveyed from line 1 to line 2 by the set _. Sets are introduced in a section of the introduction.

We also can use a set with an arbitrarily long name:

area[name="Köln"]->.extralongname;
nwr[amenity=cafe](area.extralongname);
out center;

But of course it does not work if the names of the sets in the two lines are not equal:

area[name="Köln"]->.extralongname;
nwr[amenity=cafe](area.extralnogname);
out center;

Set names are in many situations necessary to supply multiple filters with their respective input. We can search for cafés in Münster but the Overpass API then does not know which Münster is meant. There are small towns called Münster beside the large one, and these have cafés, too:

area[name="Münster"];
nwr[amenity=cafe](area);
out center;

We can overcome the problem by requesting that the café must be situated both in Münster and in North Rhine-Westphalia:

area[name="Nordrhein-Westfalen"]->.a;
area[name="Münster"]->.b;
nwr[amenity=cafe](area.a)(area.b);
out center;

The cafés are selected in line 3: We filter for objects of the type node, way, or relation that carry the tag amenity=cafe and that are situated in an area stored in a (in fact one area, i.e. the federal state of North Rhine-Westphalia) and that are situated in an area stored in b (all the cities, suburbs, and towns with name Münster). Thus, only the cafés in Münster in North Rhine-Westphalia are left.

The interaction between multiple filters and pipelining will be elaborated on further in the next section.

For the sake of completeness, we demontrate that the principle of indirect filters works for all types. We want to get all bridges over the river Alster.

We can select the river by two different approaches: first, as ways:

way[name="Alster"][waterway=river];
out geom;

We select all objects of type way that bear the tag name with value Alster and the tag waterway with value river. These are delivered in set _ from line 1 to line 2. Subsequently, the content of _ is printed in line 2.

We can select the bridges over the river instead of the river as follows:

way[name="Alster"][waterway=river];
way(around:0)[bridge=yes];
out geom;

The filter (around:0) in line 2 is here the indirect filter. We select in line 2 all ways that have the tag bridge with value yes and that have a distance of 0 to the objects of the set _. For that purpose, we have collected in line 1 into the set _ all ways in whose surroundings we want to find results, i.e. the ways that have a tag name with value Alster and a tag waterway with value river.

The whole thing works as well with relations ...

relation[name="Alster"][waterway=river];
out geom;

... now the bridges:

relation[name="Alster"][waterway=river];
way(around:0)[bridge=yes];
out geom;

Referenced Objects

We have met a completely different application of pipelining in the subsections Relations and Relations on Top of Relations of section Geometries: The traditional OpenStreetMap data model accepts coordinates only on nodes, but geometry is a crucial feature of other objects as well. Thus in the traditional model, ways and relations must be accompanied by their auxiliary nodes.

We explain the aspects of pipelining with an example: The tube line Waterloo & City in London can be obtained as follows:

rel[ref="Waterloo & City"];
out geom;

Then we employ an extended data model that is not supported by all downstream tools. If we instead use the traditional degree of detail out for printing, then we do not see any result on the map:

rel[ref="Waterloo & City"];
out;

The relation is after the output statement in line 2 still in the set _. Thus, we can collect the ways and nodes by combining an union statement with pipelining. The union statement is introduced in the following section.

rel[ref="Waterloo & City"];
out;
(
  way(r);
  node(w);
);
out skel;

Set _ contains the relations before line 3 like mentioned above. Lines 3 to 6 constitute the union statement. Line 4 thus is executed next after line 2 and gets the relations as input. The statement selects ways that match the filter (r), i.e. ways that are referenced by one or more relations from the input set. It replaces the content of the set _ with its result. According to its semantics, union keeps a copy of this result for its own result.

The statement node(w) in line 5 thus sees in set _ the ways from line 4. It selects nodes that match the filter (w), i.e. are referenced by one or more ways from its input, the ways found in line 4. It again replaces the set _ with its own result, but union subsequently anyway replaces that set again.

The union statement writes as result of line 6 the union of the results it has seen. Thus we get all ways that are referenced by the relations from line 2 and all nodes that are referenced by these ways.

Relations can have nodes as immediate members and these relations do have such members. One can see this in the Data tab or per request:

rel[ref="Waterloo & City"];
node(r);
out;

This way we replace in the set _ in line 2 the relations by the referenced nodes. Then we have in line 3 these nodes available to print them, but we need the relations again to get the referenced ways. Can we avoid the double query?

Yes, with named sets:

rel[ref="Waterloo & City"];
out;
(
  node(r)->.directly_referenced_by_the_relations;
  way(r);
  node(w);
);
out skel;

In detail:

Because this is a very frequent task, there is a shortcut for it:

rel[ref="Waterloo & City"];
out;
>;
out skel;

Lines 1 and 2 work as before, and line 4 works like line 8 in the example before. The chevron in line 3 has as semantics that it selects the ways and nodes that are directly or indirectly referenced by relations from its input set, here the set _, and writes them into the set _.

Finally, some downstream tools rely on the fixed order in the file: they need all nodes first, then all ways, and then in the end all relations.

One can alter our request here by moving the initial statement into the union block:

(
  rel[ref="Waterloo & City"];
  node(r)->.direkt_von_den_relations_referenziert;
  way(r);
  node(w);
);
out;

Similarly with the chevron:

(
  rel[ref="Waterloo & City"];
  >;
);
out;

Difference

...

Tags of Equal Value

...


next: Combining by And and Or