Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/jbarrasa/goingmeta/llms.txt

Use this file to discover all available pages before exploring further.

Session 3 of Going Meta (broadcast April 5, 2022) shows how to enforce data quality rules on a Neo4j graph using SHACL — the W3C Shapes Constraint Language. Rather than relying on application-layer checks or ad-hoc Cypher assertions, SHACL lets you declare constraints in a portable, standards-based format. Jesús loads the Northwind dataset, defines shapes for Supplier and Product nodes in Turtle, and uses the n10s n10s.validation.shacl procedures to validate the graph and report violations — including configurable severity levels.

What You Will Learn

  • What SHACL NodeShapes and PropertyShapes are and how to express them in Turtle
  • Using n10s.validation.shacl.import.inline and n10s.validation.shacl.import.fetch to load shapes
  • Running n10s.validation.shacl.validate() and interpreting its output columns
  • Filtering validation results by focusNode, severity, and resultPath
  • Defining custom severity levels (sh:Violation, sh:Warning, sh:Info) to triage data-quality issues
  • Using n10s.validation.shacl.listShapes() to introspect which shapes apply to a node type

The Northwind SHACL Shapes

The shapes file defines constraints for Supplier and Product nodes. Here is the complete northwind-shacl.ttl used in the session:
@prefix ex:    <http://example.neo4j.com/graphvalidation#> .
@prefix sh:    <http://www.w3.org/ns/shacl#> .
@prefix neo4j: <neo4j://graph.schema#> .
@prefix xsd:   <http://www.w3.org/2001/XMLSchema#> .

ex:SupplierShape a sh:NodeShape ;
  sh:targetClass neo4j:Supplier ;
  sh:property [
    sh:path neo4j:companyName ;
    sh:pattern "^\\w[^&]*$" ;
    sh:maxCount 1 ;
    sh:datatype xsd:string ;
  ] ;
  sh:property [
    sh:path neo4j:country ;
    sh:in ( "UK" "USA" "Japan" "Spain" "Australia" "Sweden"
            "Brazil" "Germany" "Italy" "Norway" "France"
            "Denmark" "Netherlands" "Finland" "Canada" ) ;
    sh:datatype xsd:string ;
  ] ;
  sh:closed true ;
  sh:ignoredProperties (
    neo4j:phone neo4j:supplierID neo4j:city
    neo4j:postalCode neo4j:address neo4j:region
  ) .


ex:ProdShape a sh:NodeShape ;
  sh:targetClass neo4j:Product ;
  sh:property [
    sh:path neo4j:productName ;
    sh:pattern "^\\w[\\s\\w\\.]*$" ;
    sh:maxCount 1 ;
    sh:datatype xsd:string ;
  ] ;
  sh:property [
    sh:path neo4j:unitPrice ;
    sh:minExclusive 10 ;
    sh:maxInclusive 100 ;
    sh:maxCount 1 ;
  ] ;
  sh:property [
    sh:path neo4j:supplied_by ;
    sh:class neo4j:Supplier ;
    sh:minCount 2 ;
  ] .
sh:closed true on SupplierShape means any property not listed in sh:property or sh:ignoredProperties will trigger a violation. This is a strict mode suited to well-governed data domains.

Validation Walkthrough

1

Load a minimal shape inline

Start with a single constraint on Supplier.companyName to see the pattern:
CALL n10s.validation.shacl.import.inline('
@prefix ex:    <http://example.neo4j.com/graphvalidation#> .
@prefix sh:    <http://www.w3.org/ns/shacl#> .
@prefix neo4j: <neo4j://graph.schema#> .
@prefix xsd:   <http://www.w3.org/2001/XMLSchema#> .

ex:SupplierShape a sh:NodeShape ;
  sh:targetClass neo4j:Supplier ;
  sh:property [
    sh:path neo4j:companyName ;
    sh:pattern "^\\\\w[^&]*$" ;
    sh:maxCount 1 ;
    sh:datatype xsd:string ;
  ] .
', 'Turtle')
2

Run the initial validation

CALL n10s.validation.shacl.validate()
3

Introduce a violation manually

Set a companyName to an array value so that sh:maxCount 1 is breached:
MATCH (s:Supplier) WITH s LIMIT 1
SET s.companyName = [s.companyName, replace(s.companyName, " ", "")]
RETURN s
4

Validate again and observe the violation

CALL n10s.validation.shacl.validate()
5

Load the full Northwind shapes

CALL n10s.validation.shacl.import.fetch(
  "https://raw.githubusercontent.com/jbarrasa/goingmeta/main/session03/shapes/northwind-shacl.ttl",
  "Turtle"
)
6

Inspect active shapes for Supplier

CALL n10s.validation.shacl.listShapes()
YIELD target, propertyOrRelationshipPath, param, value
WHERE target = 'Supplier'
RETURN target, propertyOrRelationshipPath, param, value
7

Run full validation and filter by node

CALL n10s.validation.shacl.validate()
YIELD focusNode, nodeType, shapeId, propertyShape,
      offendingValue, resultPath, severity, resultMessage
WHERE focusNode = 20
RETURN focusNode, nodeType, shapeId, propertyShape,
       offendingValue, resultPath, severity, resultMessage

Custom Severity Levels

SHACL defines three built-in severity levels: sh:Violation, sh:Warning, and sh:Info. You can assign a severity to each shape so that critical issues are distinguished from informational ones.
CALL n10s.validation.shacl.import.fetch(
  "https://raw.githubusercontent.com/jbarrasa/goingmeta/main/session03/shapes/northwind-custom-sev-shacl.ttl",
  "Turtle"
)
After loading the custom-severity shapes, aggregate violations by level to get a data-quality dashboard:
CALL n10s.validation.shacl.validate()
YIELD focusNode, nodeType, shapeId, propertyShape,
      offendingValue, resultPath, severity, resultMessage
RETURN n10s.rdf.getIRILocalName(severity), count(*)
Use severity levels to implement a data-quality traffic-light system: treat sh:Violation as blocking issues that must be fixed before data is published, and sh:Warning / sh:Info as non-blocking improvements to track over time.

Resources

Watch the Recording

Full live-stream recording of Going Meta Session 3 on YouTube.

Session Code on GitHub

SHACL shapes files and all validation queries from this session.

Build docs developers (and LLMs) love