Semantic Web and Web 3.0 · class 11 · demo
One query, two graphs
Neither half answers alone: the manufacturer's name is only in the domain graph, the block only on the chain.
?certificate appears in both GRAPH blocks of examples/06-indexer/cross.rq, so it joins them.
| Manufacturer | ?certificate | ?block | ?transaction | ?anchored | Status |
|---|---|---|---|---|---|
| Acme Lda | certificate:2026-001 | 8412991 | 0x5ebcd5…937c1d | true | anchored |
| Barros & Filhos, S.A. | certificate:2026-002 | 8412992 | 0x607da5…57203e | true | revoked |
| Cerdeira Industrial | certificate:2026-003 | — | — | false | not anchored |
The first five columns are the result of cross.rq. Cerdeira's certificate exists in the domain but was never anchored: ?block is unbound, so ?anchored is false — the difference only the crossing shows.
The Status column is not in cross.rq: the demo also reads onto:revoked of the same record ?r. Writing that
column in SPARQL, with BIND and IF, is TODO 8 of the challenge.
How it ran
The query, as in the example (data/cross.rq):
PREFIX onto: <https://data.csoares.me/onto#>
PREFIX schema: <https://schema.org/>
PREFIX prov: <http://www.w3.org/ns/prov#>
SELECT ?manufacturer ?certificate ?block ?transaction ?anchored WHERE {
# GRAPH restricts a pattern to one named graph of the dataset.
GRAPH <https://data.csoares.me/graph/domain> {
?f a onto:Manufacturer ;
schema:name ?manufacturer ;
onto:hasCertificate ?certificate .
}
# OPTIONAL keeps the manufacturer even when the chain has nothing for it:
# ?block and ?transaction are then simply unbound.
OPTIONAL {
GRAPH <https://data.csoares.me/graph/chain> {
?r a onto:OnChainRecord ;
onto:document ?certificate ;
onto:block ?block ;
onto:transaction ?transaction .
}
}
# BOUND(?x) is true when the OPTIONAL part matched.
BIND (BOUND(?block) AS ?anchored)
}
ORDER BY ?manufacturerThere is no SPARQL engine in this process (rdflib, in cross.py, is Python). The same graph patterns are
matched here in JavaScript (lib/rdf.mjs: bgp, optional), live, on every request:
GRAPH <…/graph/domain> 21 triples
?f a onto:Manufacturer .
?f schema:name ?manufacturer .
?f onto:hasCertificate ?certificate .
→ 3 rows
OPTIONAL GRAPH <…/graph/chain> 19 triples
?r a onto:OnChainRecord .
?r onto:document ?certificate .
?r onto:block ?block .
?r onto:transaction ?transaction .
→ 3 rows, 2 with ?block bound
BIND (BOUND(?block) AS ?anchored)
ORDER BY ?manufacturerThe domain graph
A copy of examples/06-indexer/domain.ttl, in <https://data.csoares.me/graph/domain>: three manufacturers, three
certificates. Nothing in it says anything about the chain.
@prefix onto: <https://data.csoares.me/onto#> .
@prefix schema: <https://schema.org/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix certificate: <https://data.csoares.me/certificate/> .
@prefix manufacturer: <https://data.csoares.me/manufacturer/> .
manufacturer:501234567 a onto:Manufacturer ;
schema:name "Acme Lda"@en ;
onto:taxId "501234567" ;
onto:hasCertificate certificate:2026-001 .
manufacturer:502345678 a onto:Manufacturer ;
schema:name "Barros & Filhos, S.A."@en ;
onto:taxId "502345678" ;
onto:hasCertificate certificate:2026-002 .
manufacturer:503456789 a onto:Manufacturer ;
schema:name "Cerdeira Industrial"@en ;
onto:taxId "503456789" ;
onto:hasCertificate certificate:2026-003 .
certificate:2026-001 a onto:Certificate ;
schema:name "Supply certificate 2026-001"@en ;
onto:validUntil "2027-12-31"^^xsd:date .
certificate:2026-002 a onto:Certificate ;
schema:name "Supply certificate 2026-002"@en ;
onto:validUntil "2027-06-30"^^xsd:date .
certificate:2026-003 a onto:Certificate ;
schema:name "Supply certificate 2026-003"@en ;
onto:validUntil "2027-03-31"^^xsd:date .
An in-memory chain (the Ethereum virtual machine, @ethereumjs/evm), in this one process: no test network, no wallet, no keys, no money. Nothing a visitor does is kept.