I use DBpedia to extract information about airports with a given IATA code. The query I'm using follows. The results I'm getting include two rows for one airport; in one the city is the location, and in the other, the country is the location. How can I retrieve the type of the location (whether it's a city or country)? This is the query I'm using:
PREFIX dbpprop: <http://dbpedia.org/property/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dbpedia-owl: <http://dbpedia.org/ontology/>
PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT * WHERE {
?subject rdf:type dbpedia-owl:Airport;
rdfs:label ?label;
dbpedia-owl:location ?location;
dbpedia-owl:iataLocationIdentifier ?iata;
geo:lat ?latitude;
geo:long ?longitude.
FILTER (lang(?label) = 'en' and regex(?iata, "MGQ"))
}
In general, resources can have lots of types, because things have lots of values for the predicate rdf:type
. In this case, it sounds like you want to retrieve the associated city or country type, if one is present. If you look at the resource http://dbpedia.org/resource/Somalia, you can see that it has the type dbpedia-owl:Country
. For http://dbpedia.org/resource/Mogadishu, there's no City type, but there is settlement, and that may be the most appropriate for identifying cities.
You can use values
to specify a set of permissible values for a variable, and use optional
to get some matches, if they're present. E.g.,
select * where {
?subject rdf:type dbpedia-owl:Airport;
rdfs:label ?label;
dbpedia-owl:location ?location;
dbpedia-owl:iataLocationIdentifier ?iata;
geo:lat ?latitude;
geo:long ?longitude.
FILTER (langMatches(lang(?label),'en') && contains(?iata, "MGQ"))
optional {
values ?locationType { dbpedia-owl:Settlement dbpedia-owl:Country }
?location a ?locationType
}
}
Also note that I've used langMatches
to check language tags; that's the proper way to do that. Since the regular expression didn't do anything more than checking whether a substring occurred in a string, I've changed it to contains
.
For what it's worth, I don't know whether I've used this values
inside optional
pattern before, but I rather like it, and I expect that it may be useful in the future. It doesn't have the same effect to put the values
outside the optional
, because if you do that, then the ?locationType
always gets a value, it's just that the optional
part might not match. That is, if you take the values
outside of the optional
, you'll get four result rows: 2 locations × 2 locationTypes = 4 combinations.