Peter Hoffmann

Exploring Mountain Huts with SPARQL and Wikidata

For outdoor enthusiasts and avid hikers, searching for mountain huts or shelters is common when planning tours. In this blog post, we will retrieve information about mountain huts around a specific latitude and longitude using the powerful combination of SPARQL and Wikidata.

Understanding SPARQL

SPARQL (SPARQL Protocol and RDF Query Language) is a query language designed for querying data stored in Resource Description Framework (RDF) format. RDF provides a standard way to represent information, making it an ideal choice for querying diverse datasets.

Accessing Wikidata:

Wikidata, a collaborative knowledge base, hosts a wealth of information on various topics, including geographical features like mountain huts. By running SPARQL queries on the Wikidata platform, we can extract specific details about these huts based on their geographic coordinates.

Retrieving Mountain Huts:

Let’s look at a SPARQL query to retrieve information about mountain huts around a given latitude and longitude. The following query can be used as a starting point:

SELECT DISTINCT ?distance ?place ?placeLabel ?lat ?long ?elevation WHERE {
  SERVICE wikibase:around {
    # Items with coordinate location (P625)
    ?place wdt:P625 ?location .
    # Circle with a center point in WKT (longitude latitude)
    bd:serviceParam wikibase:center "Point(8.114444 46.521944)"^^geo:wktLiteral .
    # Circle radius in km
    bd:serviceParam wikibase:radius "10" .
    bd:serviceParam wikibase:distance ?distance .
  }

  ?place p:P625 ?coordinates .
  ?coordinates psv:P625 [
    wikibase:geoLatitude ?lat ;
    wikibase:geoLongitude ?long
  ] .

  # Instance of: bivouac shelter (Q879208) or mountain hut (Q182676)
  ?place wdt:P31 ?subclassOf .
  VALUES ?subclassOf { wd:Q879208 wd:Q182676 } .

  # Labels with fallback languages
  SERVICE wikibase:label { bd:serviceParam wikibase:language "de,gsw,en,fr,it" . }

  OPTIONAL { ?place wdt:P2044 ?elevation . }
}
ORDER BY ?distance

Replace the numeric values in the WKT literal Point(longitude latitude) with the desired coordinates. This query retrieves mountain huts within a specified radius (in this example, 10 kilometers) of the given location.

You can also search around a Wikidata location by using its Wikidata ID (e.g., Q68103 for Interlaken) as a reference:

wd:Q68103 wdt:P625 ?mainLoc .
# Use the around service
SERVICE wikibase:around {
  # Items with coordinate location (P625)
  ?place wdt:P625 ?location .
  # Circle with ?mainLoc as the center (the coordinate location)
  bd:serviceParam wikibase:center ?mainLoc .
  # Circle radius in km
  bd:serviceParam wikibase:radius "40" .
}

To try it out, just copy and paste the example into https://query.wikidata.org

You can use the Python library SPARQLWrapper to retrieve the results via an API in JSON format:

from SPARQLWrapper import SPARQLWrapper, JSON
import json

query = '''
SELECT DISTINCT ?distance ?place ?placeLabel ?lat ?long ?elevation WHERE {
  SERVICE wikibase:around {
    ?place wdt:P625 ?location .
    bd:serviceParam wikibase:center "Point(8.114444 46.521944)"^^geo:wktLiteral .
    bd:serviceParam wikibase:radius "10" .
    bd:serviceParam wikibase:distance ?distance .
  }
  ?place p:P625 ?coordinates .
  ?coordinates psv:P625 [
    wikibase:geoLatitude ?lat ;
    wikibase:geoLongitude ?long
  ] .
  ?place wdt:P31 ?subclassOf .
  VALUES ?subclassOf { wd:Q879208 wd:Q182676 } .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "de,gsw,en,fr,it" . }
  OPTIONAL { ?place wdt:P2044 ?elevation . }
}
ORDER BY ?distance
'''

user_agent = "python test"
endpoint_url = "https://query.wikidata.org/sparql"
sparql = SPARQLWrapper(endpoint_url, agent=user_agent)
sparql.setQuery(query)
sparql.setReturnFormat(JSON)
result = sparql.queryAndConvert()['results']['bindings']
print(json.dumps(result, indent=4))