FlureeLabs

Query-Time Reasoning

This page covers how to enable and use reasoning in your queries. For background concepts see Reasoning and inference; for the full list of supported OWL/RDFS constructs see the OWL & RDFS reference.

Status: Reasoning is an experimental feature. See Standards and feature flags for how to enable it.

The reasoning parameter

Add a "reasoning" key to any JSON-LD query to control which inference modes are active:

Single mode

{
  "@context": {"ex": "http://example.org/"},
  "select": ["?s"],
  "where": {"@id": "?s", "@type": "ex:Person"},
  "reasoning": "rdfs"
}

Multiple modes

{
  "select": ["?s"],
  "where": {"@id": "?s", "@type": "ex:Person"},
  "reasoning": ["rdfs", "owl2rl"]
}

Disable reasoning

{
  "select": ["?s"],
  "where": {"@id": "?s", "@type": "ex:Person"},
  "reasoning": "none"
}

Use "none" to suppress auto-enabled RDFS and any ledger-wide defaults.

Valid mode strings

StringAliasesMode
"rdfs"RDFS subclass/subproperty expansion
"owl2ql""owl-ql", "owlql"OWL 2 QL query rewriting (includes RDFS)
"owl2rl""owl-rl", "owlrl"OWL 2 RL forward-chaining materialization
"datalog"Datalog rule execution
"none"Disable all reasoning

Default behavior

When the reasoning key is absent from a query:

  • RDFS auto-enables if your data contains rdfs:subClassOf or rdfs:subPropertyOf hierarchies. This is lightweight (query rewriting only) and usually desirable.
  • OWL 2 QL, OWL 2 RL, and Datalog remain disabled unless enabled via ledger-wide configuration.

To override ledger defaults for a single query, use "reasoning": "none".

Examples

The examples below assume this schema and data have been transacted:

{
  "@context": {
    "ex": "http://example.org/",
    "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
    "owl": "http://www.w3.org/2002/07/owl#"
  },
  "insert": [
    {"@id": "ex:Student", "rdfs:subClassOf": {"@id": "ex:Person"}},
    {"@id": "ex:GradStudent", "rdfs:subClassOf": {"@id": "ex:Student"}},
    {"@id": "ex:alice", "@type": "ex:GradStudent", "ex:name": "Alice"},
    {"@id": "ex:bob", "@type": "ex:Person", "ex:name": "Bob"},

    {"@id": "ex:livesWith", "@type": "owl:SymmetricProperty"},
    {"@id": "ex:alice", "ex:livesWith": {"@id": "ex:bob"}},

    {"@id": "ex:hasAncestor", "@type": "owl:TransitiveProperty"},
    {"@id": "ex:carol", "ex:hasAncestor": {"@id": "ex:dave"}},
    {"@id": "ex:dave", "ex:hasAncestor": {"@id": "ex:eve"}},

    {"@id": "ex:hasMother", "owl:inverseOf": {"@id": "ex:childOf"}},
    {"@id": "ex:frank", "ex:hasMother": {"@id": "ex:grace"}}
  ]
}

RDFS: subclass expansion

Query for all ex:Person instances — Alice is returned even though she was only typed as ex:GradStudent:

{
  "@context": {"ex": "http://example.org/"},
  "select": ["?name"],
  "where": {
    "@id": "?s", "@type": "ex:Person",
    "ex:name": "?name"
  },
  "reasoning": "rdfs"
}

Result: ["Alice", "Bob"]

Without reasoning (or with "reasoning": "none"), only "Bob" is returned because Alice's explicit type is GradStudent, not Person.

OWL 2 RL: symmetric properties

Query who lives with Bob — Alice is inferred even though only alice livesWith bob was asserted:

{
  "@context": {"ex": "http://example.org/"},
  "select": ["?who"],
  "where": {"@id": "ex:bob", "ex:livesWith": "?who"},
  "reasoning": "owl2rl"
}

Result: ["ex:alice"]

OWL 2 RL: transitive properties

Query for all ancestors of Carol — Eve is inferred through transitivity:

{
  "@context": {"ex": "http://example.org/"},
  "select": ["?ancestor"],
  "where": {"@id": "ex:carol", "ex:hasAncestor": "?ancestor"},
  "reasoning": "owl2rl"
}

Result: ["ex:dave", "ex:eve"]

OWL 2 QL: inverse properties

Query childOf — inferred from the hasMother / inverseOf declaration:

{
  "@context": {"ex": "http://example.org/"},
  "select": ["?child"],
  "where": {"@id": "ex:grace", "ex:childOf": "?child"},
  "reasoning": "owl2ql"
}

Result: ["ex:frank"]

OWL 2 RL: domain and range inference

If your schema declares rdfs:domain and rdfs:range:

{
  "insert": [
    {"@id": "ex:teaches", "rdfs:domain": {"@id": "ex:Professor"},
                          "rdfs:range": {"@id": "ex:Course"}},
    {"@id": "ex:alice", "ex:teaches": {"@id": "ex:cs101"}}
  ]
}

Then with "reasoning": "owl2rl":

  • ex:alice rdf:type ex:Professor is inferred (from domain)
  • ex:cs101 rdf:type ex:Course is inferred (from range)

Combined modes

Enable RDFS + OWL 2 RL + Datalog together:

{
  "select": ["?s"],
  "where": {"@id": "?s", "@type": "ex:Person"},
  "reasoning": ["rdfs", "owl2rl", "datalog"],
  "rules": [
    {
      "@context": {"ex": "http://example.org/"},
      "where": {"@id": "?p", "ex:parent": {"ex:parent": "?gp"}},
      "insert": {"@id": "?p", "ex:grandparent": {"@id": "?gp"}}
    }
  ]
}

OWL 2 RL facts are materialized first, then Datalog rules run over the combined base + OWL data, and finally RDFS query rewriting is applied.

SPARQL

In SPARQL queries, reasoning is controlled via the Fluree-specific PRAGMA reasoning directive (syntax may change while the feature is experimental). Property paths (+, *, ^) provide a complementary mechanism for navigating transitive and inverse relationships directly in the query pattern — see SPARQL for details.

Interaction with ledger configuration

If f:reasoningDefaults is set in the ledger configuration graph (see Setting groups), those modes are the baseline for every query. The per-query reasoning parameter can:

  • Add modes — the query modes are merged with the defaults.
  • Disable all"reasoning": "none" overrides the defaults entirely.

The f:overrideControl setting on the ledger config determines whether query-time overrides are allowed. See Override control for details.

Performance considerations

ModeOverheadCaching
RDFSNegligible — query rewriting onlyN/A
OWL 2 QLNegligible — query rewriting onlyN/A
OWL 2 RLFirst query materializes derived facts; subsequent queries use cacheLRU cache (16 entries), keyed on database state + reasoning modes
DatalogEach unique rule set + database state combination is cachedSame LRU cache as OWL 2 RL

Tips:

  • Start with RDFS if you only need class/property hierarchies — it has virtually zero overhead.
  • Use OWL 2 QL when you also need inverse properties and domain/range inference but want to stay in the query-rewriting approach.
  • Use OWL 2 RL when you need the full rule set (transitive, symmetric, functional properties, owl:sameAs, restrictions, property chains).
  • The materialization cache is invalidated when the underlying data changes (new transactions), so the first query after a write will re-materialize.

Related pages

TopicPage
Conceptual introductionReasoning and inference
Custom inference rulesDatalog rules
Supported OWL & RDFS constructsOWL & RDFS reference
Ledger-wide reasoning configSetting groups