cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Incorrect SHACL validation

contzero
Node Link

Hello everyone,

I'm facing an issue when trying to validate my Graph against a SHACL constraint file.
Here is my SHACL constraint :

@prefix EbomMbom: http://example.org/EbomMbom# .
@prefix dash: http://datashapes.org/dash# .
@prefix owl: http://www.w3.org/2002/07/owl# .
@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# .

http://example.org/EbomMbom
a owl:Ontology ;
owl:imports http://datashapes.org/dash ;
owl:versionInfo "Created with TopBraid Composer" ;
.
EbomMbom:Engine
a rdfs:Class ;
a sh:NodeShape ;
rdfs:subClassOf rdfs:Resource ;
sh:property [
a sh:PropertyShape ;
sh:path EbomMbom:isConnectedWith ;
sh:class EbomMbom:Fuel_Tank ;
sh:maxCount 2 ;
sh:minCount 2 ;
sh:name "is connected with" ;
sh:nodeKind sh:IRI ;
] ;
.
EbomMbom:Fuel_Tank
a rdfs:Class ;
a sh:NodeShape ;
rdfs:subClassOf rdfs:Resource ;

Basically, my constraint is to say that any instance of my Engine class has to be related to exactly 2 instances of my Fuel_Tank class through the 'isConnectedWith' relationship.
For testing purposes, I created in my graph an 'Engine_1' instance and linked it to 3 Fuel_Tank instances. The constraint is thus violated
When I launch the validation of my graph in Neo4J through the call n10s.validation.shacl.validate query, I get this result :


The offending value here is null which I cannot make sense of
Do you have an idea of what went wrong?
Thanks a lot for your help!

M.Z

1 ACCEPTED SOLUTION

Hi @contzero ,
I've been able to reproduce your example:

╒═══════════╤══════════╤════════════════════════════╤════════════════════════════════════════════════════════╤════════════════╤═════════════════╤══════════════════════════════════════╤═══════════════════════════════╕
│"focusNode"│"nodeType"│"shapeId"                   │"propertyShape"                                         │"offendingValue"│"resultPath"     │"severity"                            │"resultMessage"                │
╞═══════════╪══════════╪════════════════════════════╪════════════════════════════════════════════════════════╪════════════════╪═════════════════╪══════════════════════════════════════╪═══════════════════════════════╡
│5          │"Engine"  │"bnode://id/node1f14123pkx1"│"http://www.w3.org/ns/shacl#MaxCountConstraintComponent"│null            │"isConnectedWith"│"http://www.w3.org/ns/shacl#Violation"│"unnacceptable  cardinality: 3"│
└───────────┴──────────┴────────────────────────────┴────────────────────────────────────────────────────────┴────────────────┴─────────────────┴──────────────────────────────────────┴───────────────────────────────┘

Actually, nothing went wrong, the thing is the offending value is generally used when the violation comes from a property value (regex, datatype, minvalue...). But because the violation you're finding has to do with the cardinality of a relationship (MaxCountConstraintComponent), the offending value field is left as null.
But instead, you have the following elements to make sense of the constraint violation:

  • The resultMessage field with a description of the problem: "unnacceptable cardinality: 3"`
  • The nodeType field with the type of the problematic node: "Engine" in our case.
  • The focus node field, with the id of the problematic node. All you need to do is look it up by id. This cypher can help you:
match (n) where id(n) = 5 return n

In my case, this returns the node representing the Engine that has the three tanks.

I hope this helps,

JB.

View solution in original post

6 REPLIES 6

Hi @contzero ,
I've been able to reproduce your example:

╒═══════════╤══════════╤════════════════════════════╤════════════════════════════════════════════════════════╤════════════════╤═════════════════╤══════════════════════════════════════╤═══════════════════════════════╕
│"focusNode"│"nodeType"│"shapeId"                   │"propertyShape"                                         │"offendingValue"│"resultPath"     │"severity"                            │"resultMessage"                │
╞═══════════╪══════════╪════════════════════════════╪════════════════════════════════════════════════════════╪════════════════╪═════════════════╪══════════════════════════════════════╪═══════════════════════════════╡
│5          │"Engine"  │"bnode://id/node1f14123pkx1"│"http://www.w3.org/ns/shacl#MaxCountConstraintComponent"│null            │"isConnectedWith"│"http://www.w3.org/ns/shacl#Violation"│"unnacceptable  cardinality: 3"│
└───────────┴──────────┴────────────────────────────┴────────────────────────────────────────────────────────┴────────────────┴─────────────────┴──────────────────────────────────────┴───────────────────────────────┘

Actually, nothing went wrong, the thing is the offending value is generally used when the violation comes from a property value (regex, datatype, minvalue...). But because the violation you're finding has to do with the cardinality of a relationship (MaxCountConstraintComponent), the offending value field is left as null.
But instead, you have the following elements to make sense of the constraint violation:

  • The resultMessage field with a description of the problem: "unnacceptable cardinality: 3"`
  • The nodeType field with the type of the problematic node: "Engine" in our case.
  • The focus node field, with the id of the problematic node. All you need to do is look it up by id. This cypher can help you:
match (n) where id(n) = 5 return n

In my case, this returns the node representing the Engine that has the three tanks.

I hope this helps,

JB.

contzero
Node Link

Thanks a lot Jesus!
Actually I was missing the 'resultMessage' argument in my n10s.validation.shacl command, now it's much more clear!
Do you think there is a way to return in the same n10s.validation query the label of the focus Node (focusNode.label doesn't work) ?
M. Zemmama

Great to hear that helped, Mehdi
Maybe I should reorder the fields so that the more relevant are immediately obvious...

Not sure I understand what you mean. I think the nodeType field is exactly that, isn't it?
I see that you're getting the focusNode = 44 and the nodeType= Engine

Or am I missing something?

JB.

contzero
Node Link

Thanks for your reply Jesus. Actually here, 'Engine' is the class to which the focusNode 44 (which is an instance/NamedIndividual) belongs. My question was if we could display in the grid the label of this instance/NamedIndividual and not just its Id ?

M.Z

That is a very good point: How to identify the focus node.
When the instance data is imported from RDF it shows the uri which is an unambiguous global identifier but when it's not RDF data the only element that's always there is the internal id. But you're right, probably something more descriptive would be better/more user friendly.

JB

contzero
Node Link

Thanks a lot for your clarifications and support Jesus!

MZ