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
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' )
Run the initial validation
CALL n10s . validation . shacl . validate ()
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
Validate again and observe the violation
CALL n10s . validation . shacl . validate ()
Load the full Northwind shapes
CALL n10s . validation . shacl . import . fetch (
"https://raw.githubusercontent.com/jbarrasa/goingmeta/main/session03/shapes/northwind-shacl.ttl" ,
"Turtle"
)
Inspect active shapes for Supplier
CALL n10s . validation . shacl . listShapes ()
YIELD target , propertyOrRelationshipPath , param , value
WHERE target = 'Supplier'
RETURN target , propertyOrRelationshipPath , param , value
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.