Skip to content

Select datasets from a registry

ManualDatasetSelection hard-codes the datasets a pipeline processes. This guide shows how to drive the pipeline from a DCAT-AP 3.0 dataset registry instead, so new datasets flow in without a code change.

Point the pipeline at the registry

Create a Client for the registry’s SPARQL endpoint and pass it to RegistrySelector as the pipeline’s dataset selector:

typescript
import { Client } from '@lde/dataset-registry-client';
import { Pipeline, RegistrySelector } from '@lde/pipeline';

const pipeline = new Pipeline({
  datasetSelector: new RegistrySelector({
    registry: new Client(new URL('https://example.com/registry/sparql')),
  }),
  // …
});

Without further options the selector fetches every dataset in the registry. Results are paginated, so selection memory stays bounded regardless of registry size.

Narrow the selection with criteria

Pass criteria to select only matching datasets – for example, only those with a SPARQL endpoint or an RDF data dump:

typescript
import { rdfMediaTypes, sparqlMediaTypes } from '@lde/dataset';

const selector = new RegistrySelector({
  registry: new Client(new URL('https://example.com/registry/sparql')),
  criteria: {
    distribution: {
      mediaType: {
        $in: [...sparqlMediaTypes, ...rdfMediaTypes],
      },
    },
  },
});

Criteria follow the dataset schema, so any schema property can be matched. Two more operators cover the common cases $in doesn’t:

  • $id selects a single dataset by IRI – useful when a pipeline run targets exactly one registry entry.
  • $filter injects a raw SPARQL expression; write ?value for the property being filtered.

Combined, they select one dataset while excluding some of its distributions:

typescript
const selector = new RegistrySelector({
  registry: new Client(new URL('https://example.com/registry/sparql')),
  criteria: {
    $id: 'https://example.com/dataset/123',
    distribution: {
      accessURL: { $filter: '!CONTAINS(STR(?value), "edm")' },
    },
  },
});

See the @lde/dataset-registry-client reference for the full query interface.

Use a custom query for anything else

When criteria can’t express the selection, pass a SPARQL CONSTRUCT query instead – query takes precedence over criteria:

typescript
const selector = new RegistrySelector({
  registry: new Client(new URL('https://example.com/registry/sparql')),
  query: constructQuery,
});

Compose selectors

DatasetSelector is a one-method interface – select(): Promise<Paginator<Dataset>> – so composing selection strategies is just wrapping one selector in another plain object. For example, prefer a manual list but fall back to the registry when it selects nothing:

typescript
import type { DatasetSelector } from '@lde/pipeline';

class FallbackSelector implements DatasetSelector {
  constructor(
    private readonly primary: DatasetSelector,
    private readonly fallback: DatasetSelector,
  ) {}

  async select() {
    const selected = await this.primary.select();
    return selected.total > 0 ? selected : this.fallback.select();
  }
}

The same shape covers other compositions, such as injecting per-dataset configuration onto the selected datasets before the pipeline sees them.

In production

This is exactly how @lde/search-indexer selects its datasets: its REGISTRY_ENDPOINT and DATASET_CRITERIA environment variables feed a RegistrySelector at startup.

Released under the MIT License.