Unlock the Power of EU Data: Your Comprehensive SPARQL Journey with CELLAR
Master SPARQL from fundamentals to advanced querying on EUR-LEX's vast legal knowledge graph, CELLAR.
Welcome to your in-depth tutorial on SPARQL (SPARQL Protocol and RDF Query Language), the standard query language for Linked Data. This guide will take you from the very basics to sophisticated querying techniques, using practical examples centered around CELLAR, the common metadata repository and knowledge graph of the Publications Office of the European Union. CELLAR underpins vital EU resources like EUR-Lex, offering a rich dataset of EU law, publications, and related information. My knowledge cutoff is Tuesday, 2025-05-06.
Key Insights: Your SPARQL Launchpad
- SPARQL is SQL for Graphs: Understand how SPARQL queries RDF (Resource Description Framework) data, which is structured as interconnected subject-predicate-object triples, forming a graph.
- CELLAR is Your Playground: Learn to navigate the EU's extensive legal and publication metadata stored in CELLAR, using its specific ontology (the Common Data Model - CDM).
- From Simple to Sophisticated: Progress systematically from basic
SELECTqueries to advanced features likeOPTIONALpatterns,UNIONclauses, aggregations,CONSTRUCTqueries, and inference.
Understanding the Foundations: SPARQL and RDF in CELLAR
Before diving into writing queries, it's crucial to grasp what SPARQL and RDF are, and how they relate to CELLAR.
What is RDF? The Language of Linked Data
Resource Description Framework (RDF) is a W3C standard for describing resources on the web. Data in RDF is represented as a collection of **triples**. Each triple consists of a:
- Subject: The entity being described (e.g., a specific EU regulation).
- Predicate: A property or relationship of the subject (e.g., "has title" or "was published on date").
- Object: The value of the property or another entity related to the subject (e.g., "Regulation (EU) 2024/123" or "2024-03-15").
These triples link together to form a "knowledge graph," a web of interconnected data. CELLAR is such a knowledge graph, containing metadata about EU legal acts, publications, and more.
What is SPARQL? Querying the Graph
SPARQL is the query language specifically designed for RDF data. Think of it as the SQL equivalent for graph databases. Instead of querying tables and rows, SPARQL queries for patterns of triples within the RDF graph. It allows you to retrieve, manipulate, and explore the interconnected data stored in systems like CELLAR.
CELLAR: The EU's Knowledge Hub
CELLAR is the Publications Office of the European Union's common repository for metadata and content. It serves as the backbone for platforms like EUR-Lex. By providing a machine-readable SPARQL endpoint, CELLAR allows users and applications to directly query its vast collection of EU law and policy information. The official SPARQL endpoint for CELLAR is: https://publications.europa.eu/webapi/rdf/sparql.
To effectively query CELLAR, understanding its ontology, primarily the Common Data Model (CDM), is essential. Prefixes are used in SPARQL queries to shorten long URIs (Uniform Resource Identifiers) that define these ontologies.
Common prefixes for CELLAR include:
cdm: <http://publications.europa.eu/ontology/cdm#>(CELLAR Data Model)eli: <http://data.europa.eu/eli/ontology#>(European Legislation Identifier)dcterms: <http://purl.org/dc/terms/>(Dublin Core Terms, for metadata like title, date)skos: <http://www.w3.org/2004/02/skos/core#>(Simple Knowledge Organization System, for concepts and labels)xsd: <http://www.w3.org/2001/XMLSchema#>(XML Schema Datatypes, for literal types like dates and numbers)
CELLAR, like other large data repositories, relies on significant data center infrastructure.
The Anatomy of a SPARQL Query
A typical SPARQL query has several clauses that define what you're looking for and how the results should be presented.
Core Query Clauses
PREFIX: Defines abbreviations (prefixes) for long URIs, making queries more readable.SELECT: Specifies the variables (data points) you want to retrieve in your results. Variables in SPARQL usually start with a?or$.WHERE: Contains the graph pattern to match against the data. This is where you define the triple patterns (subject, predicate, object) you are searching for.FROM/FROM NAMED: Specifies the dataset(s) to query. For CELLAR, you typically query its public endpoint, but sometimes you might target specific named graphs within it.
Solution Modifiers
ORDER BY: Sorts the results based on one or more variables.LIMIT: Restricts the number of results returned. Crucial for testing and managing large datasets.OFFSET: Skips a specified number of results, useful for pagination.
This mindmap illustrates the key components involved in constructing a SPARQL query:
(Subject Predicate Object)"] id1_4_2["FILTER"] id1_4_3["OPTIONAL"] id1_4_4["UNION"] id1_4_5["GRAPH"] id2["Modifiers"] id2_1["ORDER BY"] id2_2["LIMIT"] id2_3["OFFSET"] id2_4["GROUP BY"] id2_5["HAVING"] id3["Variables
(e.g., ?title, ?date)"] id4["Data Types & Literals
(e.g., xsd:date, strings, numbers)"] id5["Functions
(e.g., COUNT(), YEAR(), CONTAINS())"]
Basic SPARQL Queries with CELLAR Examples
Example 1: Retrieving Titles of Legal Documents
Let's start with a simple query to find the titles of some legal "Works" (a common entity type in CELLAR) and their URIs.
PREFIX cdm: <http://publications.europa.eu/ontology/cdm#>
PREFIX dcterms: <http://purl.org/dc/terms/>
SELECT ?work ?title
WHERE {
?work a cdm:Work . # ?work is of type cdm:Work
?work dcterms:title ?title . # ?work has a dcterms:title, which is ?title
}
LIMIT 10
Explanation:
PREFIX cdm: ...andPREFIX dcterms: ...define shorthand for common CELLAR and Dublin Core namespaces.SELECT ?work ?title: We want to retrieve the URI of the work (?work) and its title (?title).WHERE { ... }: This block contains the triple patterns.?work a cdm:Work .: This matches any subject (bound to?work) that is an instance of (ais shorthand forrdf:type)cdm:Work.?work dcterms:title ?title .: This matches triples where the subject is the same?work, the predicate isdcterms:title, and the object is bound to?title.LIMIT 10: Restricts the output to the first 10 results found.
Example 2: Filtering Results by Date
Now, let's find legal documents published after a specific date and order them.
PREFIX cdm: <http://publications.europa.eu/ontology/cdm#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?work ?title ?date
WHERE {
?work a cdm:Work ;
dcterms:title ?title ;
cdm:date_document ?date . # In CELLAR, cdm:date_document is often used
FILTER (?date > "2023-01-01"^^xsd:date)
}
ORDER BY DESC(?date)
LIMIT 5
Explanation:
PREFIX xsd: ...is added for XML Schema Datatypes, necessary for specifyingxsd:date.- The semicolon
;is a shorthand. After the first triple pattern (?work a cdm:Work), it means the next triple pattern (dcterms:title ?title) shares the same subject (?work). cdm:date_document ?date: Matches the document date. Note: Predicate names for dates can vary (e.g.,dcterms:date,cdm:datePublished,cdm:work_date_document). Consulting CELLAR's documentation is key.FILTER (?date > "2023-01-01"^^xsd:date): This clause restricts results to documents where the?dateis after January 1, 2023. The^^xsd:datecasts the string to an XSD date type for proper comparison.ORDER BY DESC(?date): Sorts the results by date in descending order (most recent first).
This video provides an excellent introduction to writing your first SPARQL SELECT query, a fundamental skill for exploring CELLAR.
Example 3: Finding Regulations on a Specific Topic (String Matching)
Let's find regulations (a specific type of cdm:Work) whose titles contain the word "environment".
PREFIX cdm: <http://publications.europa.eu/ontology/cdm#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
SELECT ?regulation ?title ?subjectLabel
WHERE {
?regulation a cdm:Regulation ; # ?regulation is of type cdm:Regulation
dcterms:title ?title .
# Option 1: Filter by title (less precise, but good for exploration)
# FILTER(CONTAINS(LCASE(?title), "environment"))
# Option 2: Filter by subject matter (more precise if using controlled vocabularies)
?regulation cdm:subjectMatter ?subjectConcept .
?subjectConcept skos:prefLabel ?subjectLabel .
FILTER(CONTAINS(LCASE(?subjectLabel), "environment"))
}
LIMIT 10
Explanation:
?regulation a cdm:Regulation: Narrows down to entities specifically typed ascdm:Regulation.- The query shows two approaches to finding "environment" related documents:
- Filtering directly on the
?titleusingCONTAINS(LCASE(?title), "environment").LCASEconverts the title to lowercase for case-insensitive matching. - A more structured approach involves linking the regulation to its
cdm:subjectMatter(which is usually a concept URI) and then getting the human-readable label (skos:prefLabel) for that concept. This is generally more reliable if the data is well-annotated with controlled vocabularies like EuroVoc.
- Filtering directly on the
Intermediate SPARQL: Optional Data, Unions, and Aggregations
Example 4: Retrieving Optional Information with OPTIONAL
Sometimes, a piece of information might not exist for all resources. OPTIONAL allows you to retrieve it if present, without excluding the resource if it's missing.
PREFIX cdm: <http://publications.europa.eu/ontology/cdm#>
PREFIX dcterms: <http://purl.org/dc/terms/>
SELECT ?work ?title ?publicationDate ?entryIntoForceDate
WHERE {
?work a cdm:Work ;
dcterms:title ?title ;
cdm:date_document ?publicationDate . # Assuming this is the main publication date
OPTIONAL {
?work cdm:date_entry_into_force ?entryIntoForceDate . # This date may not exist for all works
}
}
LIMIT 10
Explanation:
- The query retrieves works, their titles, and publication dates.
OPTIONAL { ?work cdm:date_entry_into_force ?entryIntoForceDate . }: It attempts to find thecdm:date_entry_into_force. If a work has this property,?entryIntoForceDatewill be bound. If not, the work is still included in the results, but?entryIntoForceDatewill be unbound (empty) for that specific result row.
Example 5: Combining Results with UNION
The UNION clause combines results from two or more graph patterns. For example, finding both Regulations and Directives published in a specific year.
PREFIX cdm: <http://publications.europa.eu/ontology/cdm#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?document ?title ?type
WHERE {
{
?document a cdm:Regulation ;
dcterms:title ?title ;
cdm:date_document ?date .
BIND("Regulation" AS ?type)
FILTER(YEAR(?date) = 2023)
}
UNION
{
?document a cdm:Directive ;
dcterms:title ?title ;
cdm:date_document ?date .
BIND("Directive" AS ?type)
FILTER(YEAR(?date) = 2023)
}
}
LIMIT 10
Explanation:
- The first block looks for
cdm:Regulationdocuments from 2023. - The second block looks for
cdm:Directivedocuments from 2023. UNIONcombines the results from both blocks.BIND("Regulation" AS ?type)creates a new variable?typeand assigns it a string value to help distinguish the document type in the results.YEAR(?date)is a function that extracts the year from anxsd:dateorxsd:dateTimeliteral.
Example 6: Aggregating Data with GROUP BY and COUNT
SPARQL supports aggregate functions like COUNT, SUM, AVG, MIN, MAX, often used with GROUP BY.
Let's count the number of regulations published per year.
PREFIX cdm: <http://publications.europa.eu/ontology/cdm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT (YEAR(?date) AS ?year) (COUNT(?regulation) AS ?regulationCount)
WHERE {
?regulation a cdm:Regulation ;
cdm:date_document ?date .
FILTER(BOUND(?date)) # Ensure date exists for YEAR() function
}
GROUP BY YEAR(?date)
ORDER BY DESC(?year)
LIMIT 10
Explanation:
(YEAR(?date) AS ?year): Extracts the year from?dateand assigns it to a new variable?year.(COUNT(?regulation) AS ?regulationCount): Counts the number of regulations found for each group and assigns it to?regulationCount.FILTER(BOUND(?date)): Ensures that we only process entries where?datehas a value, asYEAR()might error on unbound values.GROUP BY YEAR(?date): Groups the results by the extracted year. The aggregate functionCOUNTthen operates on each group.ORDER BY DESC(?year): Sorts the yearly counts, showing the most recent years first.
The following table summarizes common SPARQL clauses and their utility when querying CELLAR:
| Clause | Description | Simplified CELLAR Example Snippet |
|---|---|---|
PREFIX |
Defines a shorthand for a URI namespace. | PREFIX cdm: <http://publications.europa.eu/ontology/cdm#> |
SELECT |
Specifies the variables to be returned in the results. | SELECT ?work ?title |
WHERE |
Contains the graph patterns to match against the data. | WHERE { ?work a cdm:Work . } |
FILTER |
Restricts results based on a condition. | FILTER (LANG(?title) = "en") |
OPTIONAL |
Allows parts of the query to match if data exists, but doesn't fail if it's absent. | OPTIONAL { ?work cdm:summary ?summary . } |
UNION |
Combines results from multiple graph patterns. | { ?doc a cdm:Regulation } UNION { ?doc a cdm:Directive } |
ORDER BY |
Sorts the results. | ORDER BY ?date_document |
LIMIT |
Restricts the number of results returned. | LIMIT 20 |
OFFSET |
Skips a specified number of results (for pagination). | OFFSET 10 |
GROUP BY |
Groups rows that have the same values into summary rows. Used with aggregate functions. | GROUP BY ?type (COUNT(?doc) AS ?count) |
CONSTRUCT |
Returns an RDF graph constructed from the query results, rather than a table. | CONSTRUCT { ?work cdm:title ?title . } WHERE { ... } |
Advanced SPARQL: CONSTRUCT, Property Paths, Named Graphs, and Inference
Example 7: Creating RDF with CONSTRUCT
While SELECT returns tabular data, CONSTRUCT returns a new RDF graph based on the matched patterns. This is useful for transforming or exporting subsets of data.
PREFIX cdm: <http://publications.europa.eu/ontology/cdm#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX mydata: <http://example.org/mydata#> # Custom prefix
CONSTRUCT {
?work mydata:europeanTitle ?title .
?work mydata:publishedOn ?date .
}
WHERE {
?work a cdm:Regulation ;
dcterms:title ?title ;
cdm:date_document ?date .
FILTER(LANG(?title) = "en" && YEAR(?date) = 2023)
}
LIMIT 5
Explanation:
CONSTRUCT { ... }: Defines the template for the RDF triples to be created. Here, it creates new triples using a custommydata:predicate.- The
WHEREclause selects English-titled regulations from 2023. - The output will be an RDF graph (e.g., in Turtle or RDF/XML format), not a table.
Example 8: Navigating Relationships with Property Paths
Property paths provide a concise way to specify traversals over one or more predicate links in the graph.
For example, to find a document and another document it amends (eli:amends), and potentially documents that amend the amendment (a chain).
PREFIX eli: <http://data.europa.eu/eli/ontology#>
PREFIX dcterms: <http://purl.org/dc/terms/>
SELECT ?originalDoc ?amendingDoc ?titleOriginal ?titleAmending
WHERE {
?amendingDoc eli:amends+ ?originalDoc . # '+' means one or more occurrences of eli:amends
?originalDoc dcterms:title ?titleOriginal .
?amendingDoc dcterms:title ?titleAmending .
FILTER(LANG(?titleOriginal) = "en" && LANG(?titleAmending) = "en")
}
LIMIT 5
Explanation:
eli:amends+: This property path means "one or more sequentialeli:amendsrelationships."predicate*: Zero or more occurrences.predicate?: Zero or one occurrence.predicate1 / predicate2: A sequence ofpredicate1followed bypredicate2.predicate1 | predicate2: Eitherpredicate1orpredicate2.
Example 9: Querying Specific Named Graphs with GRAPH
RDF data can be organized into "named graphs." CELLAR might use named graphs to partition data (e.g., by year, dataset type). You can query a specific named graph.
PREFIX cdm: <http://publications.europa.eu/ontology/cdm#>
PREFIX dcterms: <http://purl.org/dc/terms/>
# This is a hypothetical graph URI; actual CELLAR graph URIs need to be discovered
# FROM NAMED <http://publications.europa.eu/resource/graph/eurlex/directory_codes>
SELECT ?concept ?label
WHERE {
GRAPH <http://publications.europa.eu/resource/graph/eurlex/directory_codes> { # Replace with an actual CELLAR named graph URI
?concept a skos:Concept ;
skos:prefLabel ?label .
FILTER(LANG(?label) = "en")
}
}
LIMIT 10
Explanation:
GRAPH <graph-uri> { ... }: The triple patterns inside the curly braces will only be matched against the data within the specified named graph.- Discovering relevant named graph URIs in CELLAR requires exploring its documentation or querying for available graphs.
Example 10: Using Inference in CELLAR
Some SPARQL endpoints can perform inference, deriving new triples based on ontologies and rules. CELLAR supports this. For instance, if A is a subclass of B, and X is an instance of A, inference can deduce X is also an instance of B.
DEFINE input:inference "cdm_rule_set" # Instruction to activate CELLAR's inference rules
PREFIX cdm: <http://publications.europa.eu/ontology/cdm#>
PREFIX dcterms: <http://purl.org/dc/terms/>
SELECT ?document ?title
WHERE {
# This query might return more results with inference enabled
# if cdm:LegalDocument is a superclass of more specific types like cdm:Regulation
?document a cdm:LegalDocument ;
dcterms:title ?title .
FILTER(LANG(?title) = "en")
}
LIMIT 10
Explanation:
DEFINE input:inference "cdm_rule_set": This non-standard (but used by CELLAR's Virtuoso backend) directive enables a predefined set of inference rules. The specific rule set name (cdm_rule_set) is specific to CELLAR.- With inference, queries can return results that are logically implied but not explicitly stated in the raw data.
The capabilities of different SPARQL query forms can be visualized. While SELECT is for data retrieval, CONSTRUCT is for graph generation, ASK for boolean checks, and DESCRIBE for resource descriptions. This radar chart offers a conceptual comparison:
Tools and Best Practices for Querying CELLAR
- CELLAR SPARQL Endpoint: The primary interface for submitting queries is https://publications.europa.eu/webapi/rdf/sparql. Many SPARQL clients can connect to this URL.
- Flint SPARQL Editor: The EU Law and Publications Portal often provides access to tools like Flint, offering a user interface for writing and executing queries against CELLAR.
- Programming Libraries:
- R: The
eurlexpackage simplifies interaction with EU data sources, including constructing and running SPARQL queries on CELLAR. - Python: Libraries like
pyeurlexor general-purpose RDF libraries (e.g.,rdflibwithSPARQLWrapper) allow programmatic access to CELLAR.
- R: The
- Understand the CELLAR Ontology (CDM): Familiarize yourself with the Common Data Model. The Publications Office provides documentation on the structure, classes (e.g.,
cdm:Work,cdm:Regulation), and properties (e.g.,dcterms:title,cdm:date_document) used in CELLAR. This is crucial for writing effective queries. - Start Simple and Iterate: Begin with basic queries and gradually add complexity. Use
LIMITextensively during development to get quick feedback. - Check Predicate Names: Property names can be specific. For example, while
dcterms:dateis standard, CELLAR often usescdm:date_documentorcdm:work_date_documentfor the main date of a document.
Frequently Asked Questions (FAQ)
What is the difference between SPARQL and SQL?
SQL (Structured Query Language) is designed for relational databases, which store data in tables with rows and columns. SPARQL is designed for RDF (Resource Description Framework) data, which is stored as a graph of interconnected triples (subject-predicate-object). While both are query languages, they operate on fundamentally different data models. SPARQL excels at navigating relationships and querying heterogeneous, linked data.
How do I find the correct predicates (properties) to use for CELLAR data?
The best way is to consult the official documentation for CELLAR and its Common Data Model (CDM) provided by the EU Publications Office. You can also explore existing data by querying for all predicates associated with a known resource URI (e.g., SELECT DISTINCT ?p WHERE { <known_uri> ?p ?o . }) or by using a SPARQL endpoint's browsing interface if available.
Why are my SPARQL queries slow or timing out?
Large, complex RDF datasets like CELLAR can lead to slow queries if they are not optimized. Common reasons include:
- Very broad patterns that match too many triples initially.
- Complex
FILTERconditions applied late in the query. - Extensive use of
OPTIONALpatterns without sufficient constraints. - Not using
LIMITduring testing.
WHERE clause. Use FILTERs strategically. Break down complex queries into smaller parts if feasible.
What are common resource types in CELLAR?
CELLAR's Common Data Model (CDM) defines various resource types. Some frequently encountered ones include:
cdm:Work: The abstract concept of a publication or legal act (e.g., a specific regulation).cdm:Expression: A specific version or language of a Work (e.g., the English PDF version of a regulation).cdm:Manifestation: A concrete embodiment of an Expression (e.g., a particular file format like PDF or HTML).cdm:Regulation,cdm:Directive,cdm:Decision: Specific types of legal acts.cdm:LegalResource: A broader category for legal documents.
Recommended Further Exploration
To deepen your understanding of SPARQL and CELLAR, consider exploring these related queries:
- How can I retrieve all available language versions of a specific EU document from CELLAR using SPARQL?
- Show me SPARQL examples for finding relationships between EU legal acts in CELLAR, such as amendments or repeals.
- What are the EuroVoc subject matters associated with EU directives on renewable energy in CELLAR, queried via SPARQL?
- Can you explain how to use SPARQL subqueries to analyze data within CELLAR, for instance, finding documents with the most amendments?
References
Last updated May 6, 2025