-
Notifications
You must be signed in to change notification settings - Fork 8
Linked Data Fragments
SPARQL endpoints are expensive to run. And generally have low availability.
The other alternative is to serve you triples as flat files, but these can be hard to fit in memory.
Linked Data Fragments provides a specificaiton that aims for the space between these approaches. It is a lightweight protocol that allows you to expose linked data, but for the SPARQL execution to be performed at the client end.
The Linked Data Fragments specification is in draft and is under active development
- Linked data fragments homepage
- Linked data fragments spec
- Triple pattern fragments spec
- Quad pattern fragment spec
- Example software
- Comunica
With a SPARQL enpdoint, you send a SPARQL query to a server, this is interpreted, executed and the results sent to you.
With Linked Data Fragments, the SPARQL execution happens in the client (think a library running on your computer). This client takes your query then it requests the data that is needs to meet the requirements of the SPARQL query. This means that more data than is needed by the user is requested from the server, but the request itself is very quick to execute on the server....this reduces the compute load on the server at the expense of additional data transfer.
In LD Explorer goto "Sources -> Catalog -> DBPedia (TPF endpoint)"
W3C specifications can be a bit tricky to read until you are used to them, but essentially you need to do a few things.
- Return paged triples (or quads), based on a simple filter that allows the client to specify Subject, Predicate, Object (,Graph)
- With the triples, return metadata that allows the client to navigate the results
- If no filter is specified return the first page of results with no filter and appropriate metadata
Your response will need to include various parts...
Any prefixes you use (optional)
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix hydra: <http://www.w3.org/ns/hydra/core#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix void: <http://rdfs.org/ns/void#> .
A named graph that contains the metadata, the name of the graph is server URL + #metadata
<https://theUrl.com/fragmentServer#metadata> {
Within this metatdata graph
- Subject
server URL + #datasetPredicaterdf:typeObjecthydra:Collection - Subject
server URL + #datasetPredicaterdf:typeObjectvoid:Dataset - Subject
server URL + #datasetPredicatevoid:subsetObjectserver URL + query string - Subject
server URL + #datasetPredicatehydra:searchObjectblank nodes as below- These define how the server expects to recieve its filters in the
hydra:templateand, - How the different parts of this map to the concepts of
rdf:Subject,rdf:Predicateandrdf:Objectwithhydra:mapping
- These define how the server expects to recieve its filters in the
<https://theUrl.com/fragmentServer#dataset>
rdf:type hydra:Collection , void:Dataset;
void:subset <https://theUrl.com/fragmentServer?predicate=http://xmlns.com/foaf/0.1/name&object=\\u0022Alice\\u0022>;
hydra:search [ hydra:mapping [ hydra:property rdf:object;
hydra:variable "object"
];
hydra:mapping [ hydra:property rdf:predicate;
hydra:variable "predicate"
];
hydra:mapping [ hydra:property rdf:subject;
hydra:variable "subject"
];
hydra:template "https://theUrl.com/fragmentServer{?subject,predicate,object}"
] .
- Subject
server URL + #metadataPredicatefoaf:primaryTopicObjectserver URL + query string
<https://theUrl.com/fragmentServer#metadata>
foaf:primaryTopic <https://theUrl.com/fragmentServer?predicate=http://xmlns.com/foaf/0.1/name&object=\\u0022Alice\\u0022> .
- Subject
server URL + query stringPredicaterdf:typeObjecthydra:PartialCollectionView - Subject
server URL + query stringPredicatevoid:subsetObjectserver URL + query string - Subject
server URL + query stringPredicatevoid:triplesObjectliteral representing total number of triples - Subject
server URL + query stringPredicatevoid:firstObjectURL of the first page of results - Subject
server URL + query stringPredicatehydra:itemsPerPageObjectliteral representing number of triples per page - Subject
server URL + query stringPredicatevoid:nextObjectURL of the next page of results(if relevant) - Subject
server URL + query stringPredicatevoid:previousObjectURL of the previous page of results(if relevant) - Subject
server URL + query stringPredicatehydra:totalItemsObjectliteral representing total number of triples
<https://theUrl.com/fragmentServer?predicate=http://xmlns.com/foaf/0.1/name&object=\\u0022Alice\\u0022>
rdf:type hydra:PartialCollectionView;
void:subset <https://theUrl.com/fragmentServer?predicate=http://xmlns.com/foaf/0.1/name&object=\\u0022Alice\\u0022>;
void:triples "1"^^<http://www.w3.org/2001/XMLSchema#long>;
hydra:first <https://theUrl.com/fragmentServer?predicate=http://xmlns.com/foaf/0.1/name&object=\\u0022Alice\\u0022&page=1>;
hydra:itemsPerPage "2"^^<http://www.w3.org/2001/XMLSchema#long>;
hydra:next <https://theUrl.com/fragmentServer?predicate=http://xmlns.com/foaf/0.1/name&object=\\u0022Alice\\u0022&page=2>;
hydra:totalItems "1"^^<http://www.w3.org/2001/XMLSchema#long> .
End of the named graph for metadata
}
Actual data triples
<http://example.org/alice>
foaf:name "Alice" .
Comunica is a knowledge graph querying framework, it is what sits under the LD-Explorer UI.
Comunica makes some performance optimisations that are not quite compliant with the specifications. This means that the order of the triples in the metadata section is important (the order in the examples works). And you need some of the optional components from the spec (again what is in the example works).
Without these, it'll still work, but your metadata triples will get mixed in with your data by the client.
With a query string
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix hydra: <http://www.w3.org/ns/hydra/core#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix void: <http://rdfs.org/ns/void#> .
<https://theUrl.com/fragmentServer#metadata> {
<https://theUrl.com/fragmentServer#dataset>
rdf:type hydra:Collection , void:Dataset;
void:subset <https://theUrl.com/fragmentServer?predicate=http://xmlns.com/foaf/0.1/name&object=\\u0022Alice\\u0022>;
hydra:search [ hydra:mapping [ hydra:property rdf:object;
hydra:variable "object"
];
hydra:mapping [ hydra:property rdf:predicate;
hydra:variable "predicate"
];
hydra:mapping [ hydra:property rdf:subject;
hydra:variable "subject"
];
hydra:template "https://theUrl.com/fragmentServer{?subject,predicate,object}"
] .
<https://theUrl.com/fragmentServer#metadata>
foaf:primaryTopic <https://theUrl.com/fragmentServer?predicate=http://xmlns.com/foaf/0.1/name&object=\\u0022Alice\\u0022> .
<https://theUrl.com/fragmentServer?predicate=http://xmlns.com/foaf/0.1/name&object=\\u0022Alice\\u0022>
rdf:type hydra:PartialCollectionView;
void:subset <https://theUrl.com/fragmentServer?predicate=http://xmlns.com/foaf/0.1/name&object=\\u0022Alice\\u0022>;
void:triples "1"^^<http://www.w3.org/2001/XMLSchema#long>;
hydra:first <https://theUrl.com/fragmentServer?predicate=http://xmlns.com/foaf/0.1/name&object=\\u0022Alice\\u0022&page=1>;
hydra:itemsPerPage "2"^^<http://www.w3.org/2001/XMLSchema#long>;
hydra:next <https://theUrl.com/fragmentServer?predicate=http://xmlns.com/foaf/0.1/name&object=\\u0022Alice\\u0022&page=2>;
hydra:totalItems "1"^^<http://www.w3.org/2001/XMLSchema#long> .
}
<http://example.org/alice>
foaf:name "Alice" .
With no query string
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix hydra: <http://www.w3.org/ns/hydra/core#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix void: <http://rdfs.org/ns/void#> .
<https://theUrl.com/fragmentServer#metadata> {
<https://theUrl.com/fragmentServer#dataset>
rdf:type hydra:Collection , void:Dataset;
void:subset <https://theUrl.com/fragmentServer>;
hydra:search [ hydra:mapping [ hydra:property rdf:object;
hydra:variable "object"
];
hydra:mapping [ hydra:property rdf:predicate;
hydra:variable "predicate"
];
hydra:mapping [ hydra:property rdf:subject;
hydra:variable "subject"
];
hydra:template "https://theUrl.com/fragmentServer{?subject,predicate,object}"
] .
<https://theUrl.com/fragmentServer#metadata>
foaf:primaryTopic <https://theUrl.com/fragmentServer> .
<https://theUrl.com/fragmentServer>
rdf:type hydra:PartialCollectionView;
void:subset <https://theUrl.com/fragmentServer>;
void:triples "7"^^<http://www.w3.org/2001/XMLSchema#long>;
hydra:first <https://theUrl.com/fragmentServer?page=1>;
hydra:itemsPerPage "2"^^<http://www.w3.org/2001/XMLSchema#long>;
hydra:next <https://theUrl.com/fragmentServer?page=2>;
hydra:totalItems "7"^^<http://www.w3.org/2001/XMLSchema#long> .
}
<http://example.org/alice>
foaf:knows <http://example.org/bob>;
foaf:name "Alice" .
© Crown Copyright GCHQ 2026 - This content is licensed under the Open Government License 3.0