Help with QLever queries: OR operator and suffixess

Using QLever, I want to find elements that have a main tag x, but do not have a tag y OR z.
Random example: find building=* without building:levels=* or building:colour=*. Is this possible?

Also, is there a syntax to search for tags with suffixes? For example, find elements with every variation of the name tag (name, name:en, name:es, name:it ecc.) in one line?

?osm osmkey:building ?building_type .
MINUS {
  ?osm osmkey:building:levels ?building_levels .
}
MINUS {
  ?osm osmkey:building:colour ?building_colour .
}

In Sophox, instead of MINUS, use the more performant FILTER NOT EXISTS, which is unimplemented in QLever so far.

Keys are stored as predicates prefixed by osmkey:, which is equivalent to <https://www.openstreetmap.org/wiki/Key:>.

?osm ?key ?name .
FILTER(STRSTARTS(STR(?key), CONCAT(osmkey:, "name")))

Filters and function calls are generally less performant than triple statements. To avoid memory limits (and potentially bringing down the server), you’ll want to qualify this query by a specific tag you’re looking for or an area to search within.

Sophox is more performant with filters. It can perform a similar query using the osmd: prefix instead of osmkey:.

I’m not a programmer, I’m trying to understand.

?osm osmkey:building ?building_type .

finds all the elements with Tag:building=*

MINUS {
  ?osm osmkey:building:levels ?building_levels .
}

Removes from all the previous elements all the elements that have Tag:building:levels=*

MINUS {
  ?osm osmkey:building:colour ?building_colour .
}

Again, it removes from the already shortened list the elements that have Tag:building:colour=*. Is this correct?

In this case isn’t the resulting list a list of building=* without building:levels=* and building:colours=* instead that a list of building=* without building:levels=* or building:colours=*? Unless I’m missing something

Correct, MINUS is equivalent to the (…; - …;) syntax in OverpassQL. This is the same query in pseudocode:

  • Select all the elements that:
    • have building=*
  • except for the elements that:
    • have building:levels=*
  • except for the elements that:
    • have building:colour=*

With the following query, each result has building=*, and some have neither building:levels=* nor building:colour=*, but no result has both building:levels=* and building:colour=* together:

?osm osmkey:building ?building_type .
MINUS {
  ?osm osmkey:building:levels ?building_levels .
  ?osm osmkey:building:colour ?building_colour .
}

The same query in pseudocode:

  • Select all the elements that:
    • have building=*
  • except for the elements that:
    • have building:levels=* and
    • have building:colour=*

With the following query, each result will have building=* plus one of building:levels=* or building:colour=* but not both:

?osm osmkey:building ?building_type .
?osm (osmkey:building:levels|osmkey:building:colour) ?building_levels_or_colour .
MINUS {
  ?osm osmkey:building:levels ?building_levels .
  ?osm osmkey:building:colour ?building_colour .
}

The same query in pseudocode:

  • Select all the elements that:
    • have building=* and
    • have either building:levels=* or building:colour=*
  • except for the elements that:
    • have building:levels=* and
    • have building:colour=*

If you ever need to “or” two constraints that aren’t as straightforward, here’s a more verbose syntax to accomplish the same result:

?osm osmkey:building ?building_type .
{
  ?osm osmkey:building:levels ?building_levels .
} UNION {
  ?osm osmkey:building:colour ?building_colour .
}
MINUS {
  ?osm osmkey:building:levels ?building_levels .
  ?osm osmkey:building:colour ?building_colour .
}