Create a Shapes Graph
You can create a shapes graph by writing and loading a Turtle file or by running a SPARQL INSERT query. This topic provides guidance and examples for creating and loading a shapes graph. For information about the constraints that are supported in shapes graphs, see Constraint Component Reference.
Each shapes graph can contain up to 60 shapes. To load more than 60 shapes, create multiple graphs.
Defining Shapes in a TTL File
The following example shows a .ttl file that configures shape constraints on employee data. The file includes comments and messages that explain the constraints.
# employee_shapes.ttl @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . @prefix sh: <http://www.w3.org/ns/shacl#> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . @prefix ex: <http://example.org/> . ex:EmployeeShape a sh:NodeShape ; sh:targetClass ex:Employee ; sh:property [ sh:path ex:hasID ; sh:minCount 1 ; sh:maxCount 1 ; sh:datatype xsd:string ; sh:pattern "^[0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]$" ; sh:message "Every employee must have an ID that matches the pattern" ; ] ; sh:property [ sh:path ex:employeeType ; sh:minCount 1 ; sh:maxCount 1 ; sh:datatype xsd:string ; sh:in ("Manager" "Worker" "Contractor") ; sh:message "Every employee is a manager, worker, or contractor" ; ] ; sh:property [ sh:path ex:birthYear ; sh:maxInclusive 2007 ; sh:datatype xsd:integer ; sh:message "Birth year must be 2007 or earlier" ; ] ; sh:property [ sh:path ex:hasTitle ; sh:datatype xsd:string ; sh:minCount 1 ; sh:message "Must have a title but may have more than one" ; ] ; sh:or ( # All employees must have a supervisor except for the President [ sh:path ex:hasSupervisor ; sh:minCount 1 ; sh:maxCount 1 ; sh:class ex:Employee ; ] [ sh:path ex:hasTitle ; sh:hasValue "President" ; ] ) ; sh:or ( # Every employee must have an hourly wage or salary [ sh:path ex:hasSalary ; sh:minCount 1 ; sh:maxCount 1 ; ] [ sh:path ex:hasWage ; sh:minCount 1 ; sh:maxCount 1 ; ] ) ; sh:property [ sh:path ex:hasSalary ; sh:datatype xsd:double ; sh:minInclusive 30000.00 ; sh:message "Salary must be 30,000 or higher" ; ] ; sh:property [ sh:path ex:hasWage ; sh:datatype xsd:double ; sh:minInclusive 15.00 ; sh:message "Wage must be at least 15.00" ; ] .
To create the shapes graph, load the file to Graph Lakehouse. For example, the following query loads the TTL file from a mounted file system into a graph named <http://anzograph.com/employeeShapes>
:
LOAD <file:/mnt/shared/data/employee_shapes.ttl> INTO GRAPH <http://anzograph.com/employeeShapes>
For more information about loading files, see Load RDF Data from Files.
Creating Shapes with an INSERT Query
The example below shows an INSERT query that configures the same shape constraints as the TTL example above. Running the query creates a shapes graph called <http://anzograph.com/employeeShapes>
.
# employee_shapes.rq PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX sh: <http://www.w3.org/ns/shacl#> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> PREFIX ex: <http://example.org/> INSERT DATA { GRAPH <http://anzograph.com/employeeShapes> { ex:EmployeeShape a sh:NodeShape ; sh:targetClass ex:Employee ; sh:property [ sh:path ex:hasID ; sh:minCount 1 ; sh:maxCount 1 ; sh:datatype xsd:string ; sh:pattern "^[0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]$" ; sh:message "Every employee must have an ID that matches the pattern" ; ] ; sh:property [ sh:path ex:employeeType ; sh:minCount 1 ; sh:maxCount 1 ; sh:datatype xsd:string ; sh:in ("Manager" "Worker" "Contractor") ; sh:message "Every employee is a manager, worker, or contractor" ; ] ; sh:property [ sh:path ex:birthYear ; sh:maxInclusive 2007 ; sh:datatype xsd:integer ; sh:message "Birth year must be 2007 or earlier" ; ] ; sh:property [ sh:path ex:hasTitle ; sh:datatype xsd:string ; sh:minCount 1 ; sh:message "Must have a title but may have more than one" ; ] ; sh:or ( # All employees must have a supervisor except for the President [ sh:path ex:hasSupervisor ; sh:minCount 1 ; sh:maxCount 1 ; sh:class ex:Employee ; ] [ sh:path ex:hasTitle ; sh:hasValue "President" ; ] ) ; sh:or ( # Every employee must have an hourly wage or salary [ sh:path ex:hasSalary ; sh:minCount 1 ; sh:maxCount 1 ; ] [ sh:path ex:hasWage ; sh:minCount 1 ; sh:maxCount 1 ; ] ) ; sh:property [ sh:path ex:hasSalary ; sh:datatype xsd:double ; sh:minInclusive 30000.00 ; sh:message "Salary must be 30,000 or higher" ; ] ; sh:property [ sh:path ex:hasWage ; sh:datatype xsd:double ; sh:minInclusive 15.00 ; sh:message "Wage must be at least 15.00" ; ] . } }