Skip to content

Search filter on @optional property does not exclude results #170

@ddeboer

Description

@ddeboer

Problem

When using $not (or other filters) on an @optional property in search criteria, the filter is placed inside an OPTIONAL block in the generated SPARQL. This means it doesn't exclude matching results — it only makes the optional binding unbound.

Example

Schema:

const schema = {
  '@type': 'dcat:Dataset',
  distribution: {
    '@id': 'dcat:distribution',
    '@array': true,
    '@schema': {
      '@type': 'dcat:Distribution',
      accessURL: 'dcat:accessURL',
      conformsTo: { '@id': 'dcterms:conformsTo', '@optional': true },
    },
  },
};

Search criteria:

await lens.find({
  where: {
    distribution: {
      conformsTo: { $not: 'https://www.w3.org/TR/rdf-sparql-query/' },
    },
  },
});

Generated SPARQL (actual)

OPTIONAL {
  ?iri_1 <dcterms:conformsTo> ?iri_1_1 .
  FILTER (?iri_1_1 != "https://www.w3.org/TR/rdf-sparql-query/") .
}

The FILTER is inside the OPTIONAL, so distributions with conformsTo = .../rdf-sparql-query/ still appear — their conformsTo value just becomes unbound.

Expected SPARQL

The filter should be moved outside the OPTIONAL block, using a !BOUND || != pattern:

OPTIONAL {
  ?iri_1 <dcterms:conformsTo> ?iri_1_1 .
}
FILTER (!BOUND(?iri_1_1) || ?iri_1_1 != "https://www.w3.org/TR/rdf-sparql-query/")

This would correctly exclude distributions whose conformsTo matches, while keeping distributions that have no conformsTo at all.

Version

LDkit 2.6.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions