Semantic Web and Web 3.0 · class 12 · demo
The competency queries
Every queries/*.rq of the project, run as queries.py runs them: the
{{name}} placeholders filled with the example: of the header, over the graph plus the chain and the
domain in their own named graphs. A saved query that comes back empty is the commonest way for an ontology to become decorative.
1 row links-under-review.rq
The matches left in the grey zone, waiting for human review.
# The matches left in the grey zone, waiting for human review.
PREFIX onto: <https://data.csoares.me/onto#>
PREFIX prov: <http://www.w3.org/ns/prov#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
SELECT ?subject ?object ?confidence WHERE {
?l onto:predicate skos:closeMatch ;
onto:subject ?subject ; onto:object ?object ; onto:confidence ?confidence .
}
ORDER BY DESC(?confidence)| ?subject | ?object | ?confidence |
|---|---|---|
| manufacturer:2 | manufacturer:506789012 | 0.6 |
Take away default graph (provenance) and the result changes.
2 rows manufacturers-by-country.rq
How many manufacturers there are per country.
# How many manufacturers there are per country.
PREFIX onto: <https://data.csoares.me/onto#>
SELECT ?country (COUNT(DISTINCT ?f) AS ?manufacturers) WHERE {
?f a onto:Manufacturer ; onto:country ?country .
}
GROUP BY ?country
ORDER BY DESC(?manufacturers)| ?country | ?manufacturers |
|---|---|
| country:PT | 5 |
| country:ES | 1 |
Take away graph:suppliers-csv and the result changes.
3 rows manufacturers-in-two-sources.rq
Manufacturers that identity resolution linked across the two sources.
# Manufacturers that identity resolution linked across the two sources.
PREFIX schema: <https://schema.org/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
SELECT ?catalogue ?csv ?name WHERE {
?catalogue owl:sameAs ?csv ; schema:name ?name .
}
ORDER BY ?name| ?catalogue | ?csv | ?name |
|---|---|---|
| manufacturer:1 | manufacturer:501234567 | Acme Lda |
| manufacturer:2 | manufacturer:502345678 | Barros & Filhos, S.A. |
| manufacturer:3 | manufacturer:503456789 | Cerdeira Industrial |
Take away graph:catalogue or graph:identity and the result changes.
3 rows products-by-manufacturer.rq country=PT
Products per manufacturer, filtered by country. The catalogue has the products but no country; the country comes from the suppliers' CSV and from the aligned external source. It only returns anything because the graph crossed the sources. Grouping is by catalogue entity and not by name: once identity is resolved, the same company has several forms of the name (one per source). The country placeholder (in double braces) is replaced before the query runs: by the service, after checking the value against the pattern above; by the verifier, with the example value.
# parameter: country ^[A-Z]{2}$
# example: country=PT
# Products per manufacturer, filtered by country. The catalogue has the products but no
# country; the country comes from the suppliers' CSV and from the aligned external source.
# It only returns anything because the graph crossed the sources.
# Grouping is by catalogue entity and not by name: once identity is resolved,
# the same company has several forms of the name (one per source).
PREFIX onto: <https://data.csoares.me/onto#>
PREFIX schema: <https://schema.org/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
# The country placeholder (in double braces) is replaced before the query
# runs: by the service, after checking the value against the pattern above;
# by the verifier, with the example value.
SELECT ?manufacturer (SAMPLE(?n) AS ?name) (COUNT(DISTINCT ?p) AS ?products) WHERE {
?p a onto:Product ; onto:manufacturedBy ?manufacturer .
?manufacturer (owl:sameAs*) ?source .
?source schema:name ?n ;
onto:country <https://data.csoares.me/country/PT> .
}
GROUP BY ?manufacturer
ORDER BY DESC(?products)| ?manufacturer | ?name | ?products |
|---|---|---|
| manufacturer:1 | Acme Lda | 2 |
| manufacturer:2 | Barros & Filhos, S.A. | 2 |
| manufacturer:3 | Cerdeira Industrial Unipessoal | 1 |
Take away graph:catalogue or graph:identity or graph:suppliers-csv and the result changes.
2 rows products-of-manufacturer.rq taxId=501234567
Products of a manufacturer identified by its TAXID. owl:sameAs* finds the TAXID on any of the URIs the company has (catalogue or CSV). In this data the catalogue carries the TAXID too, so the identity graph is not needed here: take it away and the answer is the same.
# parameter: taxId ^[0-9]{9}$
# example: taxId=501234567
# Products of a manufacturer identified by its TAXID. owl:sameAs* finds the TAXID on any of
# the URIs the company has (catalogue or CSV). In this data the catalogue carries the TAXID
# too, so the identity graph is not needed here: take it away and the answer is the same.
PREFIX onto: <https://data.csoares.me/onto#>
PREFIX schema: <https://schema.org/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
SELECT DISTINCT ?product ?name WHERE {
?f onto:taxId "501234567" .
# owl:sameAs* is a property path: zero or more sameAs hops, so ?same is ?f
# itself or any entity identity resolution linked to it.
?same (owl:sameAs*) ?f .
?product a onto:Product ; onto:manufacturedBy ?same ; schema:name ?name .
}
ORDER BY ?name| ?product | ?name |
|---|---|
| product:100 | Bearing 6204 |
| product:101 | Bearing 6205 |
Take away graph:catalogue and the result changes.
2 rows provenance-of-manufacturer.rq taxId=501234567
Which file or database this manufacturer description came from, and when.
# parameter: taxId ^[0-9]{9}$
# example: taxId=501234567
# Which file or database this manufacturer description came from, and when.
PREFIX onto: <https://data.csoares.me/onto#>
PREFIX prov: <http://www.w3.org/ns/prov#>
SELECT ?graph ?source ?at WHERE {
GRAPH ?graph { ?f onto:taxId "501234567" }
?graph prov:wasDerivedFrom ?source ;
prov:generatedAtTime ?at .
}| ?graph | ?source | ?at |
|---|---|---|
| graph:suppliers-csv | file://sources/suppliers.csv | 2026-11-01T13:21:28+00:00 |
| graph:catalogue | sqlite://sources/catalogue.db | 2026-11-01T13:21:28+00:00 |
Take away default graph (provenance) or graph:catalogue or graph:suppliers-csv and the result changes.
3 rows suppliers-certificates.rq
The query that crosses the chain with the domain: for each manufacturer, the state of its supply certificate. Neither half answers this alone: the manufacturer name and the declared validity are in the domain graph; the block, the transaction and the revocation are in the chain graph. This crossing is what the defence wants. Syntax note: the slash is not allowed in the local part of a prefixed name, so the graphs appear with the IRI written out in full.
# The query that crosses the chain with the domain: for each manufacturer, the
# state of its supply certificate.
#
# Neither half answers this alone: the manufacturer name and the declared
# validity are in the domain graph; the block, the transaction and the
# revocation are in the chain graph. This crossing is what the defence wants.
#
# Syntax note: the slash is not allowed in the local part of a prefixed
# name, so the graphs appear with the IRI written out in full.
PREFIX onto: <https://data.csoares.me/onto#>
PREFIX schema: <https://schema.org/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?manufacturer ?certificate ?status ?block WHERE {
GRAPH <https://data.csoares.me/graph/domain> {
?f a onto:Manufacturer ;
schema:name ?manufacturer ;
onto:hasCertificate ?certificate .
}
# OPTIONAL: a certificate that was never anchored still appears, with
# ?block and ?revoked unbound.
OPTIONAL {
GRAPH <https://data.csoares.me/graph/chain> {
?r a onto:OnChainRecord ;
onto:document ?certificate ;
onto:block ?block ;
onto:revoked ?revoked .
}
}
# BOUND tells "no match in the OPTIONAL" apart from a value.
BIND (IF(!BOUND(?block), "not anchored",
IF(?revoked, "revoked", "anchored")) AS ?status)
}
ORDER BY ?manufacturer| ?manufacturer | ?certificate | ?status | ?block |
|---|---|---|---|
| Acme Lda | certificate:2026-001 | anchored | 8412991 |
| Barros & Filhos, S.A. | certificate:2026-002 | revoked | 8412991 |
| Cerdeira Industrial | certificate:2026-003 | not anchored | unbound |
Take away graph:chain or graph:domain and the result changes.