---
title: Construct and federation
url: https://docs.triply.cc/concepts/sparql-construct-and-federation/
description: The construct, ask and describe query forms, and querying data that lives on someone else's
  server.
---

# SPARQL: construct, ask, describe and federation

The three chapters before this one have used `select`, which returns a table. The other
three query forms return something else, and one of them — `construct` — is the
reason SPARQL is a transformation language and not only a query language.

This chapter also covers federation: querying data that lives on someone else's
server as if it were your own.

It assumes [SPARQL: the basics](https://docs.triply.cc/concepts/sparql-basics/) and
[graph patterns](https://docs.triply.cc/concepts/sparql-graph-patterns/).

## construct: a query that returns triples

`construct` matches a pattern like any other query, but instead of filling a
table it builds triples. Because its output is a graph, that output can be loaded
straight back into a dataset. Matching and writing use the same language.

There are two kinds.

**`construct where`** returns exactly what it matched. The graph that comes out
has the same shape as the graph that went in:

```sparql
prefix pokemon: <https://triplydb.com/academy/pokemon/id/pokemon/>

construct where {
  pokemon:pikachu ?p ?o.
}
```

That returns every direct property of Pikachu. Reach deeper by adding patterns —
here, following into the audio resource as well:

```sparql
prefix pokemon: <https://triplydb.com/academy/pokemon/id/pokemon/>
prefix schema:  <http://schema.org/>

construct where {
  pokemon:pikachu
    ?p ?o;
    schema:audio ?audio.
  ?audio ?y ?z.
}
```

**A templated `construct`** separates the two graphs. The `where` clause says
what to match; the `construct` clause says what to build. They need not look
alike, which is what makes this a translation:

```sparql
prefix species: <https://triplydb.com/academy/pokemon/id/species/>
prefix vocab:   <https://triplydb.com/academy/pokemon/vocab/>

construct {
  ?pokemon a ?species.
}
where {
  ?pokemon vocab:species ?species.
  filter(?species in (species:dragon, species:mouse))
}
```

The source data relates a Pokémon to its species through `vocab:species`. The
output states the same fact as a class membership. Nothing was edited; a new
shape was derived from an old one.

This is the mechanism behind most data migration in linked data. When a model
changes, you write a `construct` that reads the old shape and emits the new one.

## ask: a yes or no

`ask` returns `true` or `false`: does anything match this pattern? It does not
return the matches themselves, which makes it cheap.

Use it for checks. "Does any product lack a manufacturer?" is an `ask` query, and
a scheduled `ask` is a serviceable data quality alarm.

For structural quality checking at scale, [SHACL](https://docs.triply.cc/concepts/shacl/) is the better tool.

## describe: triples about a resource

`describe` takes an IRI and returns triples about it. It is the quickest way to
find out what a dataset holds about something.

The catch is that **what `describe` returns is not standardised**. Every
implementation decides how much of the surrounding graph to include, and that is
intentional — the form exists as a lookup for IRIs you cannot otherwise resolve.

That matters as soon as you build on it. When you need to be certain which
triples come back, use `construct`, which states exactly that.

And if you are reaching for `describe` to resolve an IRI, note that a plain HTTP
request already does that when the IRI is set up properly:

```bash
curl -H "Accept: application/n-triples" -L https://triplydb.com/academy/pokemon/id/pokemon/pikachu
```

Which is a reason to make your own IRIs resolvable.

## Changing stored data: SPARQL Update

`construct` returns a graph; it does not change one. **SPARQL Update** is the
separate language for that, with `insert data`, `delete data` and
`delete/insert … where`.

```sparql
base <https://triplydb.com/>

insert data { <john> <knows> <mary>. }
```

Keep the distinction clear: `construct` derives, Update mutates. Where both are
available, `construct` is usually the safer of the two because it leaves the source
untouched.

## Federation: querying someone else's data

A federated query runs partly on your endpoint and partly on another. The
`service` keyword marks the part that travels:

```sparql
prefix owl:     <http://www.w3.org/2002/07/owl#>
prefix pokemon: <https://triplydb.com/academy/pokemon/id/pokemon/>

construct {
  pokemon:pikachu ?p ?o.
}
where {
  pokemon:pikachu owl:sameAs ?dbpediaResource.
  service <https://dbpedia.org/sparql> {
    ?dbpediaResource ?p ?o.
    filter(isLiteral(?o))
  }
}
```

```mermaid
graph LR
  local["Your endpoint"] -- "owl:sameAs" --> bridge(("shared IRI"))
  bridge --> remote["Remote endpoint\n(service …)"]
  remote -- results --> local
```

The precondition is easy to miss: **the two endpoints must share at least one
term.** Without an IRI or literal in common there is nothing to join on. In
practice you create that overlap deliberately with `owl:sameAs`, which is exactly
the "link" in linked data.

For a sense of what is reachable this way, see the
[Linked Open Data Cloud](https://lod-cloud.net) — every dot is a queryable
dataset.

Two cautions before you build on federation. A federated query is only as
available as the slowest endpoint in it, and remote endpoints impose their own
result limits. Treat it as a way to explore and to prototype integrations, not as
a substitute for loading data you depend on.

## Where this appears in Triply products

- **Saved queries** turn a `construct` query into an API that returns triples
  rather than a table.
  See [Saved queries](https://docs.triply.cc/how-to/saved-queries/).

## Where to next

- [Querying real-world data](https://docs.triply.cc/concepts/sparql-real-world-data/) — hierarchies, geodata and
  statistics
- [SHACL](https://docs.triply.cc/concepts/shacl/) — checking data quality properly
- [Aggregation](https://docs.triply.cc/concepts/sparql-aggregation/) — back one chapter
- [SPARQL: the basics](https://docs.triply.cc/concepts/sparql-basics/) — back to the first chapter
- [Glossary](https://docs.triply.cc/reference/glossary/) — every term on this page, in one place
