Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
10-13-2022 08:10 AM
I have the following graph in neo4j:
CREATE (banana:Fruit {name:'Banana'})
CREATE (apple:Fruit {name:'Apple'})
CREATE (fruit_salad:Dish {name:'Fruit Salad'})
CREATE (banana_gun:Weapon {name:'Banana Gun'})
CREATE
(apple)-[:can_be_used_in]->(fruit_salad),
(banana)-[:can_be_used_in]->(fruit_salad),
(banana)-[:can_be_used_in]->(banana_gun)
I am trying to write a SHACL schema for validating this graph.
The tricky part here is that the relationship "can_be_used_in" can lead from Fruit to either Dish or Weapon type nodes.
I don't want to allow for any other relationships from the Fruit type, so I am using "sh:closed true ;".
I suspect what I need can be somehow done via the sh:or or sh:xone blocks.
I attempted this (the below is a Cypher query for loading the schema):
call n10s.validation.shacl.import.inline('
@prefix neo4j: <neo4j://graph.schema#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
# ---- Fruit -------------
neo4j:FruitShape a sh:NodeShape ;
sh:targetClass neo4j:Fruit ;
sh:closed true ;
sh:property [
sh:path neo4j:name ;
sh:maxCount 1 ;
sh:minCount 1 ;
sh:datatype xsd:string ;
];
sh:or(
sh:property [
sh:path neo4j:can_be_used_in ;
sh:class neo4j:Weapon ;
]
sh:property [
sh:path neo4j:can_be_used_in ;
sh:class neo4j:Dish ;
]
);
.
','Turtle')
However this gives me the following output (failed validation):
[{'focusNode': 552,
'nodeType': 'Fruit',
'shapeId': 'neo4j://graph.schema#FruitShape',
'propertyShape': 'http://www.w3.org/ns/shacl#ClosedConstraintComponent',
'offendingValue': '555, 554',
'resultPath': 'can_be_used_in',
'severity': 'http://www.w3.org/ns/shacl#Violation',
'resultMessage': 'Closed type definition does not include this property/relationship'},
{'focusNode': 553,
'nodeType': 'Fruit',
'shapeId': 'neo4j://graph.schema#FruitShape',
'propertyShape': 'http://www.w3.org/ns/shacl#ClosedConstraintComponent',
'offendingValue': '554',
'resultPath': 'can_be_used_in',
'severity': 'http://www.w3.org/ns/shacl#Violation',
'resultMessage': 'Closed type definition does not include this property/relationship'}]
I also attempted the following:
call n10s.validation.shacl.import.inline('
@prefix neo4j: <neo4j://graph.schema#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
# ---- Fruit -------------
neo4j:FruitShape a sh:NodeShape ;
sh:targetClass neo4j:Fruit ;
sh:closed true ;
sh:property [
sh:path neo4j:name ;
sh:maxCount 1 ;
sh:minCount 1 ;
sh:datatype xsd:string ;
];
sh:property [
sh:path neo4j:can_be_used_in ;
sh:or(
[
sh:class neo4j:Whatever ;
]
[
sh:class neo4j:ThisDoesntExist ;
]
);
] ;
.
','Turtle')
But this just returns an empty result (suggesting a successful validation), even though the types used in the 'or' statement don't exist. I also attempted these with sh:xone instead, and that didn't work either.
I am at a loss here, is this a SHACL/neo4j integration issue, or am I using it wrong?
Below is my full example in Python, in case it helps:
from py2neo import Graph
graph = Graph(password="test_database")
graph.delete_all()
example_graph_query = """
CREATE (banana:Fruit {name:'Banana'})
CREATE (apple:Fruit {name:'Apple'})
CREATE (fruit_salad:Dish {name:'Fruit Salad'})
CREATE (banana_gun:Weapon {name:'Banana Gun'})
CREATE
(apple)-[:can_be_used_in]->(fruit_salad),
(banana)-[:can_be_used_in]->(fruit_salad),
(banana)-[:can_be_used_in]->(banana_gun)
"""
graph.run(example_graph_query)
shacl_schema="""
call n10s.validation.shacl.import.inline('
@prefix neo4j: <neo4j://graph.schema#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
# ---- Fruit -------------
neo4j:FruitShape a sh:NodeShape ;
sh:targetClass neo4j:Fruit ;
sh:closed true ;
sh:property [
sh:path neo4j:name ;
sh:maxCount 1 ;
sh:minCount 1 ;
sh:datatype xsd:string ;
];
sh:or(
sh:property [
sh:path neo4j:can_be_used_in ;
sh:class neo4j:Weapon ;
]
sh:property [
sh:path neo4j:can_be_used_in ;
sh:class neo4j:Dish ;
]
);
.
','Turtle')
"""
shacl_schema_ver_2="""
call n10s.validation.shacl.import.inline('
@prefix neo4j: <neo4j://graph.schema#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
# ---- Fruit -------------
neo4j:FruitShape a sh:NodeShape ;
sh:targetClass neo4j:Fruit ;
sh:closed true ;
sh:property [
sh:path neo4j:name ;
sh:maxCount 1 ;
sh:minCount 1 ;
sh:datatype xsd:string ;
];
sh:property [
sh:path neo4j:can_be_used_in ;
sh:or(
[
sh:class neo4j:Whatever ;
]
[
sh:class neo4j:ThisDoesntExist ;
]
);
] ;
.
','Turtle')
"""
data = graph.run(shacl_schema).data()
validation_query="""
call n10s.validation.shacl.validate()
"""
result = graph.run(validation_query)
10-13-2022 08:15 AM
This seems to be a duplicate of https://community.neo4j.com/t5/neo4j-graph-platform/shacl-validate-nodes-have-1-class-a-and-1-class-... , which is also unsolved.
Is the answer that neosemantics doesn't support this functionality?
All the sessions of the conference are now available online