-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Node Expressions #222
Comments
I have been using Node Expressions extensively for generating SPARQL queries from shapes: https://shape-to-query.hypermedia.app/docs/ |
On the description page, I don't understand the second edg:Database-tableCount
a sh:PropertyShape ;
sh:inferredProperty edg:tableCount ;
sh:path [ ## ????
sh:count [
sh:path [
sh:inversePath edg:tableOf ;
] ;
] ;
] .
sh:datatype xsd:integer ;
sh:description "The number of tables in this database, automatically computed." ; From the description of it, this seems to be a prototype/template for a first example edg:Database-tableCount
a sh:DerivedPropertyShape ;
sh:inferredProperty edg:tableCount ;
sh:values [
sh:count [
sh:path [
sh:inversePath edg:tableOf ;
] ;
] ;
] .
sh:datatype xsd:integer ;
sh:description "The number of tables in this database, automatically computed." ; related to:
|
The first definition of tableCount used a sh:values rule, with 1.1 syntax and the sh:path of that was the (potential) inferred property. The new design is more flexible and allows the use of node expressions directly at sh:path, with the inferred property optional in case anyone wants to reference them from other node expressions. The values of sh:path at PropertyShapes in 1.2 would be more general than previously. While current SHACL only allows property path expressions, 1.2 would allow any node expression in the sh:path position. This should not be confused with the use of sh:path in the inner block (sh:inversePath), which is a node expression that must point to an "old" property path. It may be best to use a fresh property instead for this use case, instead of sh:path. Also, since property expressions such as sh:inversePath will also be node expressions, it could just be dropped in your example:
Not sure if this is any clearer, please ask again if it isn't. |
It was copied from your example :-)
It's early days, but, yes, I think a new name would be better. Maybe extend the definition of property shape to be "must have exactly one of sh:path or one sh:inferredProperty". |
The general direction proposed in Proposal on Node Expressions for SHACL Core 1.2 looks really useful for our requirements. I recorded a related use case that we've got in #227 . |
Picking up from #234 (comment)
Being able to give a name to a node expression so it can be used in several places seems a likely need. That doesn't need the full function definition (it does not need to declare parameters, or return type necessarily).
It will need a call syntax so that the node expression call site is a blank node (otherwise it is a constant term expression)
|
I also got confused with the use of expressions within sh:path. My first thought was also that the expression within a path was a way to dynamically calculate the path.
So we could have a shape that checks that the age of a person is within a valid range, without knowing the specific predicate that the subject uses to define the age. |
Here is some exploration of node expressions. Examples:
"F&O" is "XPath and XQuery Functions and Operators"
Example 1
Example 2
Example 3
Evaluation and function callingThis is my understanding of the node expressions proposal. IRIs and literals are constants ( Anything
The SHACL-AF CG extended list of node expressions has set-based functions and aggregators. They take list arguments; the examples about take single values for each argument. |
those NExp would still need to be used wherever we would allow NExp to be used right (i.e. within Shapes)? they can't just exist on their "own" (otherwise, what would sh:this point to?) |
why not adopt a similar approach like the already existing one for defining SPARQL-based Constraint components?: sh:PatternConstraintComponent
a sh:ConstraintComponent ;
sh:parameter [
sh:path sh:pattern ;
] ;
sh:parameter [
sh:path sh:flags ;
sh:optional true ;
] ;
sh:validator shimpl:hasPattern .
shimpl:hasPattern
a sh:SPARQLAskValidator ;
sh:message "Value does not match pattern {$pattern}" ;
sh:ask """
ASK {
FILTER (!isBlank($value) &&
IF(bound($flags), regex(str($value), $pattern, $flags), regex(str($value), $pattern)))
}""" . |
I think it's worth referencing the latest draft of SHACL-AF: https://w3c.github.io/shacl/shacl-af/ There, every expression is a blank node and its properties determine the functionality. The spec defines a set of expressions which have special meaning ( Everything else is treated as a function call (Function Expression). Notably, a vocabulary exists under https://datashapes.org/sparql namespace which maps SPARQL functions. Do we also want to adopt that in some fashion? @HolgerKnublauch
Other than the shorthand, the above matches the current usage of Function Expressions 👍 On that note, complex expressions quickly result in deeply nested structures which are not exactly pretty. For example, I used something like this to generate SPARQL which creates an URI from resource's kebab-cased prefix sh: <http://www.w3.org/ns/shacl#>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix sparql: <http://datashapes.org/sparql#>
PREFIX schema: <http://schema.org/>
[
a sh:NodeShape ;
sh:property [
sh:path schema:value ;
sh:values [
sparql:iri (
[
sparql:concat
(
"/prefix/"
[
sparql:encode_for_uri
(
[
sparql:replace
(
[
sparql:lcase
(
[
sh:path schema:name
]
)
] " " "-" "g"
)
]
)
]
"-"
[
sparql:substr ( [ sparql:struuid () ] 1 8 )
]
)
]
)
]
] ;
] . The SPARQL: PREFIX schema: <http://schema.org/>
CONSTRUCT { ?resource1 schema:value ?resource2. }
WHERE {
?resource1 schema:name ?resource3.
BIND(IRI(CONCAT("/prefix/", ENCODE_FOR_URI(REPLACE(LCASE(?resource3), " ", "-", "g")), "-", SUBSTR(STRUUID(), 1 , 8 ))) AS ?resource2)
} The generated patterns are arguably terser and easier to read which made me wonder every time if a different SHACL representation could be possible. |
The thing about SPARQL functions is the dispatch.
Something to share with SHACL-CS? It would be possible to reuse the expression syntax of SPARQL and translate it to node expressions in RDF form. Then the expressions aren't opaque to introspection, which has been a concern mentioned, while being easier to write and maintain. |
@tpluscode SPARQL strings could be a Compact Syntax for NEs. That's what we did in SPIN/TopBraid's user interface, allowing users to enter the SPARQL string while storing the triples. But yeah, nested bnode trees have their downsides. And yes, something like the dash-sparql library could just become another spec or part of the main NE document, depending on time. As @simonstey indicated, potentially the SHACL-SPARQL spec could be extended to allow self-descriptive purely declarative node expression types that are backed by SELECT queries that are repeatedly executed over all input bindings. The same mechanism already exists for user-defined constraint components and functions. And the built-in SPARQL functions could then be lifted into SHACL simply by making them sh:SPARQLFunctions with the actual built-in functions like CONCAT in their sh:select. As a result, anyone can plug in such libraries, producing "living" standards like an open source project. |
yes - and declarations with details can be used for checking calls. Named parameters everywhere looks to be are clunky when not used via SPARQL.
e.g.
Before we get to deep, some use cases from across the WG would be good. |
This issue is for general discussion of Node Expressions.
Node Expressions in SHACL-AF (May 2017).
SHACL CG draft with a longer list of possible node expressions
Wiki doc: Proposal on Node Expressions for SHACL Core 1.2
Use cases:
Please add use cases, small or large, as issues and label them "Inferencing" and also "UCR". We can do further organisation later if the volume is high enough.
The full work on this area is phase2.
However, some of the ideas also apply to to SHACL core in phase1. We need to know what is the vision of "node expressions" so that phase1 documents are aligned.
The text was updated successfully, but these errors were encountered: