SPARQL
Tabla de Contenido
Primeros pasos
Listado de grafos
El punto SPARQL está dividido en grafos de forma que en un grafo existen las tripletas relaciondadas con un conjunto de datos determinado. Podemos conocer los diferentes grafos existentes ejecutando la siguiente consulta SPARQL
SELECT DISTINCT ?uri WHERE { GRAPH ?uri {?s a ?t} }
Grafo | Contenido |
---|---|
https://www.zaragoza.es/turismo/restaurante/ | Restaurantes |
https://www.zaragoza.es/turismo/monumento/ | Monumentos |
https://www.zaragoza.es/cultura-ocio/evento-zaragoza/ | Agenda de actividades |
https://www.zaragoza.es/empleo/oferta/ | Oferta de empleo |
https://www.zaragoza.es/urbanismo-infraestructuras/equipamiento/urbano/ | Paradas de taxi, aparcamientos ... |
https://www.zaragoza.es/urbanismo-infraestructuras/equipamiento/recurso/ | Equipamientos/Recursos de la ciudad |
https://www.zaragoza.es/sector-publico/subvencion/ | Subvenciones |
https://www.zaragoza.es/sector-publico/contrato | Perfil del contratante |
https://www.zaragoza.es/dataset/catalogo/ | Catálogo de datos abiertos |
https://www.zaragoza.es/medio-ambiente/calidad-aire/ | Calidad del aire |
https://www.zaragoza.es/urbanismo-infraestructuras/callejero/ | Callejero, portalero e información semántica asociada |
https://www.zaragoza.es/turismo/edificio-historico/ | Catálogo de edificios históricos |
https://www.zaragoza.es/turismo/alojamiento/ | Alojamientos de la ciudad |
https://www.zaragoza.es/sector-publico/organismo/ | Estructura organizativa del ayuntamiento |
... |
Objetos de un grafo
Dentro de cada uno de los grafos están los diferentes objetos asociados. Para ver los objetos que existen dentro de un grafo podemos ejecutar la siguiente consulta. Indicando el grafo sobre el que queremos realizar la consulta.
select distinct ?uri where {[] a ?uri}
Resultado:
- https://www.zaragoza.es/api/kos/cultura-ocio/ludotecas
- https://www.zaragoza.es/api/kos/deporte/campos-de-futbol
- https://www.zaragoza.es/api/kos/salud/farmacias
- https://www.zaragoza.es/api/kos/cultura-ocio/museos
- ...
Propiedades de un objeto
Supongamos que queremos trabajar con los museos (
https://www.zaragoza.es/api/kos/cultura-ocio/museos
), en primer lugar tenemos que
conocer las propiedades que puede tener el objeto, para lo cual ejecutaremos la
siguiente consulta.
select distinct ?uri where { ?uriCont a <http://www.zaragoza.es/api/kos/cultura-ocio/museos>; ?uri ?obj. }
Propiedad | Significado |
---|---|
http://www.w3.org/1999/02/22-rdf-syntax-ns#type | Tipo |
http://purl.org/dc/terms/modified | Fecha de modificación |
http://www.w3.org/2000/01/rdf-schema#label | Nombre del recurso |
http://schema.org/name | Nombre del recurso |
http://purl.org/dc/terms/title | Nombre del recurso |
http://www.geonames.org/ontology#name | Nombre del recurso |
http://www.w3.org/2000/01/rdf-schema#comment | Descripción |
http://purl.org/dc/terms/description | Descripción |
http://schema.org/description | Descripción |
http://vocab.linkeddata.es/datosabiertos/def/turismo/lugar#accesibilidad | Información de accesibilidad |
http://schema.org/price | Precio |
http://purl.org/dc/terms/identifier | Identificador |
http://www.w3.org/2006/vcard/ns#email | Correo electrónico |
http://www.w3.org/2006/vcard/ns#street-adr | Dirección |
http://www.w3.org/2006/vcard/ns#url | Sitio web |
http://www.w3.org/2004/02/skos/core#Concept | |
http://www.w3.org/2006/vcard/ns#photo | Imagen del recurso |
http://www.w3.org/2006/vcard/ns#tel | Teléfono |
http://vocab.linkeddata.es/datosabiertos/def/turismo/lugar#gradoAccesibilidad | Grado de accesibilidad |
http://vocab.linkeddata.es/datosabiertos/def/turismo/lugar#servicios | Servicios |
http://schema.org/typicalAgeRange | Población destinataria |
http://vocab.linkeddata.es/datosabiertos/def/turismo/lugar#institucion | Institución |
http://www.w3.org/2003/01/geo/wgs84_pos#geometry | Coordenadas |
http://www.w3.org/2006/vcard/ns#category | Tipo de equipamiento |
http://purl.org/goodrelations/v1#hasOpeningHoursSpecification | Horario |
En el listado anterior aparecen repetidas propiedades para facilitar el trabajo con varios vocabularios
Contar el número de registros de un tipo determinado.
Para contar el número de registros de un tipo ejecutaríamos la siguiente consulta:
select COUNT(?Concepto) AS ?numero Where{ ?Concepto a <http://www.zaragoza.es/api/kos/cultura-ocio/museos>. }
Ejemplo de listado
Una vez hemos visto las propiedades, nos planteamos, por ejemplo, obtener un listado de
museos con las propiedades, uri del recurso, nombre, horario y el tipo
,
para lo que ejecutaríamos la siguiente consulta.
select distinct ?uriCont ?nombre ?horario ?tipo where { ?uriCont a <http://www.zaragoza.es/api/kos/cultura-ocio/museos>; <http://www.w3.org/2000/01/rdf-schema#label> ?nombre; <http://purl.org/goodrelations/v1#hasOpeningHoursSpecification> ?horario; <http://www.w3.org/2006/vcard/ns#category> ?tipo. }
En el campo tipo nos aparece su URI pero queremos el nombre del tipo, para saber qué información está almacenada sobre una uri, podemos ejecutar
describe <http://www.zaragoza.es/api/recurso/urbanismo-infraestructuras/equipamiento/subtema/144>
En el resultado vemos que el nombre del tipo está en la propiedad rdfs:label por lo que la consulta la modificaríamos de la siguiente forma
select distinct ?uriCont ?nombre ?horario ?tipo where { ?uriCont a <http://www.zaragoza.es/api/kos/cultura-ocio/museos>; <http://www.w3.org/2000/01/rdf-schema#label> ?nombre; <http://purl.org/goodrelations/v1#hasOpeningHoursSpecification> ?horario; <http://www.w3.org/2006/vcard/ns#category>/rdfs:label ?tipo. }
Observando los resultados vemos que aparecen registros repetidos porque un recurso puede tener varios tipos, por lo que vamos a concatenar los diferentes tipos en una sola columna.
select distinct ?uriCont ?nombre ?horario (group_concat(distinct ?tipo;separator=",")) as ?tipo where { ?uriCont a <http://www.zaragoza.es/api/kos/cultura-ocio/museos>; <http://www.w3.org/2000/01/rdf-schema#label> ?nombre; <http://purl.org/goodrelations/v1#hasOpeningHoursSpecification> ?horario; <http://www.w3.org/2006/vcard/ns#category>/rdfs:label ?tipo. }
A la consulta anterior vamos a añadir las coordenadas del recurso.
select distinct ?uriCont ?nombre ?horario (group_concat(distinct ?tipo;separator=",")) as ?tipo ?coordenadas where { ?uriCont a <http://www.zaragoza.es/api/kos/cultura-ocio/museos>; <http://www.w3.org/2000/01/rdf-schema#label> ?nombre; <http://purl.org/goodrelations/v1#hasOpeningHoursSpecification> ?horario; <http://www.w3.org/2006/vcard/ns#category>/rdfs:label ?tipo; <http://www.w3.org/2003/01/geo/wgs84_pos#geometry> ?coordenadas. }
Nos vuelven a salir recursos repetidos porque las coordenadas están en 3 sistemas de referencia, utm30n, etre89 y wgs84, en el ejemplo vamos a utilizar el sistema wgs84, recuperando la latitud y la longitud, con OPTIONAL para recuperar los recursos aunque no estén localizados .
select distinct ?uriCont ?nombre ?horario (group_concat(distinct ?tipo;separator=",")) as ?tipo ?latitud ?longitud where { ?uriCont a <http://www.zaragoza.es/api/kos/cultura-ocio/museos>; <http://www.w3.org/2000/01/rdf-schema#label> ?nombre; <http://purl.org/goodrelations/v1#hasOpeningHoursSpecification> ?horario; <http://www.w3.org/2006/vcard/ns#category>/rdfs:label ?tipo. optional { ?uriCont <http://www.w3.org/2003/01/geo/wgs84_pos#geometry> ?coordenadas. ?coordenadas <http://www.w3.org/2003/01/geo/wgs84_pos#lat> ?latitud; <http://www.w3.org/2003/01/geo/wgs84_pos#long> ?longitud. } }
La consulta anterior la vamos a simplificar utilizando prefijos, el prefijo rdfs no se tiene que declarar porque es uno de los reconocidos por defecto.
PREFIX cultura: <http://www.zaragoza.es/api/kos/cultura-ocio/> PREFIX gr:<http://purl.org/goodrelations/v1#> PREFIX v:<http://www.w3.org/2006/vcard/ns#> PREFIX geo:<http://www.w3.org/2003/01/geo/wgs84_pos#> select distinct ?uriCont ?nombre ?horario (group_concat(distinct ?tipo;separator=",")) as ?tipo ?latitud ?longitud where { ?uriCont a cultura:museos; rdfs:label ?nombre; gr:hasOpeningHoursSpecification ?horario; v:category/rdfs:label ?tipo. optional { ?uriCont geo:geometry ?coordenadas. ?coordenadas geo:lat ?latitud; geo:long ?longitud. } }
Podemos indicar que nos devuelva el valor sin el tipo de dato de la siguiente forma:
PREFIX cultura: <http://www.zaragoza.es/api/kos/cultura-ocio/> PREFIX gr:<http://purl.org/goodrelations/v1#> PREFIX v:<http://www.w3.org/2006/vcard/ns#> PREFIX geo:<http://www.w3.org/2003/01/geo/wgs84_pos#> select distinct ?uriCont str(?nombre) as ?nombre str(?horario) as ?horario (group_concat(distinct ?tipo;separator=",")) as ?tipo ?latitud ?longitud where { ?uriCont a cultura:museos; rdfs:label ?nombre; gr:hasOpeningHoursSpecification ?horario; v:category/rdfs:label ?tipo. optional { ?uriCont geo:geometry ?coordenadas. ?coordenadas geo:lat ?latitud; geo:long ?longitud. } }
Ejemplo de detalle
Podemos ver todas las propiedades de un recurso en concreto utilizando la siguiente consulta:
select * where { <http://www.zaragoza.es/api/recurso/urbanismo-infraestructuras/equipamiento/recurso/2174> ?prop ?value. }
Lo que ocurre es que existirán propiedades que no aparezcan en todos los recursos del mismo tipo por lo que es preferible conocer las propiedades que puede tener ese tipo de recurso, para lo cual ejecutaremos la misma consulta del apartado anterior, obteniendo el mismo resultado.
select distinct ?uri where { ?uriCont a <http://www.zaragoza.es/api/kos/cultura-ocio/museos>; ?uri ?obj. }
Con las propiedades obtenidas preparamos la consulta para obtener los datos del recurso
2174
PREFIX cultura: <http://www.zaragoza.es/api/kos/cultura-ocio/> PREFIX v: <http://www.w3.org/2006/vcard/ns#> PREFIX tur:<http://vocab.linkeddata.es/datosabiertos/def/turismo/lugar#> PREFIX gr:<http://purl.org/goodrelations/v1#> PREFIX s:<http://schema.org> SELECT ?uriCont ?nombre ?description ?infoAccesibilidad ?precio ?email ?direccion ?photo ?web ?tel ?gradoAccesibilidad ?servicios ?poblacion ?institucion ?coordenadas ?tipo ?horario ?lastUpdated WHERE { ?uriCont a cultura:museos. ?uriCont dcterms:identifier "2174". ?uriCont rdfs:label ?nombre. ?uriCont rdfs:comment ?description. ?uriCont tur:accesibilidad ?infoAccesibilidad. ?uriCont s:price ?precio. ?uriCont v:email ?email. ?uriCont v:street-adr ?direccion. ?uriCont v:photo ?photo. ?uriCont v:url ?web. ?uriCont v:tel ?tel. ?uriCont tur:gradoAccesibilidad ?gradoAccesibilidad. ?uriCont tur:servicios ?servicios. ?uriCont s:typicalAgeRange ?poblacion. ?uriCont tur:institucion ?institucion. ?uriCont geo:geometry ?coordenadas. ?uriCont v:category ?tipo. ?uriCont gr:hasOpeningHoursSpecification ?horario. ?uriCont dcterms:modified ?lastUpdated. }
Al ejecutar la consulta no nos devuelve ningún resultado por lo que añadimos
optional
a los campos:
PREFIX cultura: <http://www.zaragoza.es/api/kos/cultura-ocio/> PREFIX v: <http://www.w3.org/2006/vcard/ns#> PREFIX tur:<http://vocab.linkeddata.es/datosabiertos/def/turismo/lugar#> PREFIX gr:<http://purl.org/goodrelations/v1#> PREFIX s:<http://schema.org> SELECT ?uriCont ?nombre ?description ?infoAccesibilidad ?precio ?email ?direccion ?photo ?web ?tel ?gradoAccesibilidad ?servicios ?poblacion ?institucion ?coordenadas ?tipo ?horario ?lastUpdated WHERE { ?uriCont a cultura:museos. ?uriCont dcterms:identifier "2174". ?uriCont rdfs:label ?nombre. optional{?uriCont rdfs:comment ?description. } optional{?uriCont tur:accesibilidad ?infoAccesibilidad. } optional{?uriCont s:price ?precio. } optional{?uriCont v:email ?email. } optional{?uriCont v:street-adr ?direccion. } optional{?uriCont v:photo ?photo. } optional{?uriCont v:url ?web. } optional{?uriCont v:tel ?tel. } optional{?uriCont tur:gradoAccesibilidad ?gradoAccesibilidad. } optional{?uriCont tur:servicios ?servicios. } optional{?uriCont s:typicalAgeRange ?poblacion. } optional{?uriCont tur:institucion ?institucion. } optional{?uriCont geo:geometry ?coordenadas. } optional{?uriCont v:category ?tipo. } optional{?uriCont gr:hasOpeningHoursSpecification ?horario. } optional{?uriCont dcterms:modified ?lastUpdated. } }
Ahora vemos que nos aparecen muchos registros repetidos, tanto por los diferentes tipos como por las coordenadas en diferentes sistemas de referencia
PREFIX cultura: <http://www.zaragoza.es/api/kos/cultura-ocio/> PREFIX v: <http://www.w3.org/2006/vcard/ns#> PREFIX tur:<http://vocab.linkeddata.es/datosabiertos/def/turismo/lugar#> PREFIX gr:<http://purl.org/goodrelations/v1#> PREFIX s:<http://schema.org> SELECT ?uriCont ?nombre ?description ?infoAccesibilidad ?precio ?email ?direccion ?photo ?web ?tel ?gradoAccesibilidad ?servicios ?poblacion ?institucion ?latitud ?longitud (group_concat(distinct ?tipo;separator=",")) as ?tipo ?horario ?lastUpdated WHERE { ?uriCont a cultura:museos. ?uriCont dcterms:identifier "2174". ?uriCont rdfs:label ?nombre. optional{?uriCont rdfs:comment ?description.} optional{?uriCont tur:accesibilidad ?infoAccesibilidad.} optional{?uriCont s:price ?precio.} optional{?uriCont v:email ?email.} optional{?uriCont v:street-adr ?direccion.} optional{?uriCont v:photo ?photo.} optional{?uriCont v:url ?web.} optional{?uriCont v:tel ?tel.} optional{?uriCont tur:gradoAccesibilidad ?gradoAccesibilidad.} optional{?uriCont tur:servicios ?servicios.} optional{?uriCont s:typicalAgeRange ?poblacion.} optional{?uriCont tur:institucion ?institucion.} optional { ?uriCont geo:geometry ?coordenadas. ?coordenadas geo:lat ?latitud; geo:long ?longitud. } optional{?uriCont v:category ?tipo.} optional{?uriCont gr:hasOpeningHoursSpecification ?horario.} optional{?uriCont dcterms:modified ?lastUpdated.} }
Ahora ya podemos obtener los datos del registro sin duplicados. En algunos elementos en vez del valor nos aparece su uri, por lo que tenemos que obtener los valores de esos campos.
PREFIX cultura: <http://www.zaragoza.es/api/kos/cultura-ocio/> PREFIX v: <http://www.w3.org/2006/vcard/ns#> PREFIX tur:<http://vocab.linkeddata.es/datosabiertos/def/turismo/lugar#> PREFIX gr:<http://purl.org/goodrelations/v1#> PREFIX s:<http://schema.org> SELECT ?uriCont ?nombre ?description ?infoAccesibilidad ?precio ?email ?direccion ?photo ?web ?tel ?gradoAccesibilidad ?servicios ?poblacion ?institucion ?latitud ?longitud (group_concat(distinct ?tipo;separator=",")) as ?tipo ?horario ?lastUpdated WHERE { ?uriCont a cultura:museos. ?uriCont dcterms:identifier "2174". ?uriCont rdfs:label ?nombre. optional{?uriCont rdfs:comment ?description.} optional{?uriCont tur:accesibilidad ?infoAccesibilidad.} optional{?uriCont s:price ?precio.} optional{?uriCont v:email ?email.} optional{?uriCont v:street-adr ?direccion.} optional{?uriCont v:photo ?photo.} optional{?uriCont v:url ?web.} optional{?uriCont v:tel/v:Tel ?tel.} optional{?uriCont tur:gradoAccesibilidad ?gradoAccesibilidad.} optional{?uriCont tur:servicios ?servicios.} optional{?uriCont s:typicalAgeRange/rdfs:label ?poblacion.} optional{?uriCont tur:institucion ?institucion.} optional { ?uriCont geo:geometry ?coordenadas. ?coordenadas geo:lat ?latitud; geo:long ?longitud. } optional{?uriCont v:category/rdfs:label ?tipo.} optional{?uriCont gr:hasOpeningHoursSpecification ?horario.} optional{?uriCont dcterms:modified ?lastUpdated.} }
Formatos de respuesta
Hasta ahora al no haber seleccionado el formato veíamos los resultados en formato HTML, pero podemos indicar otros formatos como son:
- HTML
- text/html
- Spreadsheet
- application/vnd.ms-excel
- XML
- application/sparql-results+xml
- JSON
- application/sparql-results+json
- Javascript
- application/javascript
- NTriples
- text/plain
- RDF/XML
- application/rdf+xml
- CSV
- text/csv
- TSV
- text/tab-separated-values
La url resultante de la ejecución es la que podemos utilizar desde las aplicaciones, y tendrá la siguiente sintaxis:
http://datos.zaragoza.es/sparql?default-graph-uri=' + encodeURIComponent( grafo) + '&query=' + encodeURIComponent(querySPARQL) + '&format=' + encodeURIComponent(formato) + '&timeout=0
Listado de prefijos precargados en el punto SPARQL
dbpedia | http://dbpedia.org/resource/ |
dbpprop | http://dbpedia.org/property/ |
dc | http://purl.org/dc/elements/1.1/ |
dcterms | http://purl.org/dc/terms/ |
fn | http://www.w3.org/2005/xpath-functions/# |
foaf | http://xmlns.com/foaf/0.1/ |
geo | http://www.w3.org/2003/01/geo/wgs84_pos# |
gr | http://purl.org/goodrelations/v1# |
ldp | http://www.w3.org/ns/ldp# |
ogcgml | http://www.opengis.net/ont/gml# |
ogcgs | http://www.opengis.net/ont/geosparql# |