Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining whether DBpedia resources are Cities or Countries

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"))
}

SPARQL results

like image 272
Vasya Rogov Avatar asked Sep 30 '22 15:09

Vasya Rogov


1 Answers

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
  }
}

SPARQL results

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.

like image 172
Joshua Taylor Avatar answered Dec 22 '22 15:12

Joshua Taylor