Query for superproperty but only return asserted properties

Hi,

I'm having some issues in Stardog 5.2.1 regarding the use of FILTER NOT EXIST. I have the following Tbox loaded (for simplicity in the default graph).

ex:propA a owl:DatatypeProperty .
ex:propA-1 a owl:DatatypeProperty ;
	rdfs:subPropertyOf ex:propA .
ex:propA-1-1 a owl:DatatypeProperty ;
	rdfs:subPropertyOf ex:propA-1 .
ex:propA-2 a owl:DatatypeProperty ;
	rdfs:subPropertyOf ex:propA .
ex:propA-2-1 a owl:DatatypeProperty ;
	rdfs:subPropertyOf ex:propA-2 .

In my loaded Abox, I assert the following triples:

inst:object1 ex:propA-1-1 "some first value" .
inst:object1 ex:propA-2-1 "some second value" .

which infers the following triples:

inst:object1 ex:propA-1 "some first value" .
inst:object1 ex:propA "some first value" .
inst:object1 ex:propA-2 "some second value" .
inst:object1 ex:propA "some second value" .

I want to be able to query for all nodes connected by properties ex:propA if reasoning is activated and they should only return the asserted properties (which are also the most specific properties defined in the Tbox) between those two nodes.

When I do the following query in a Ontotext GraphDB (reasoning active), I get the desired result:

SELECT ?s ?p ?o WHERE {
	?s ex:propA ?o .
	?s ?p ?o .
	FILTER NOT EXISTS { 
		?fictiveSubProp rdfs:subPropertyOf ?p .
		FILTER (?p != ?fictiveSubProp)
	}
}

When I try the same in Stardog (reasoning active), I get no results back. I've figured out that I need to add the ?fictiveSubProp in a regular triple pattern to get any results back as ?fictiveSubProp is unbound. I then get all properties back (asserted + inferred) and not only the asserted ones, which is logical but not what I need...

SELECT ?s ?p ?o WHERE {
	?s ex:propA ?o .
	?s ?p ?o .
  	?fictiveSubProp a owl:DatatypeProperty
	FILTER NOT EXISTS { 
		?fictiveSubProp rdfs:subPropertyOf ?p .
		FILTER (?p != ?fictiveSubProp)
	}
}

Does anyone have suggestions to approach this in Stardog? Maybe a totally different query? The problem is that I don't know the properties that should be excluded (in the example: ex:propA-1 and ex:propA-2), so I cannot use a FILTER with an enumeration.

I come to the same conclusion if I swap FILTER NOT EXISTS for MINUS

I'm not sure about all the exact reasons for this so some of this is speculation but I was able to get it to work. I'll do my best to try to explain what I think is going on.

If you query for everything without reasoning.

SELECT * WHERE {
  ?s ?p ?o                     
}

You get the expected output

+------------+--------------------+----------------------+
|     s      |         p          |          o           |
+------------+--------------------+----------------------+
| :propA     | rdf:type           | owl:DatatypeProperty |
| :propA-1   | rdf:type           | owl:DatatypeProperty |
| :propA-1   | rdfs:subPropertyOf | :propA               |
| :propA-1-1 | rdf:type           | owl:DatatypeProperty |
| :propA-1-1 | rdfs:subPropertyOf | :propA-1             |
| :propA-2   | rdf:type           | owl:DatatypeProperty |
| :propA-2   | rdfs:subPropertyOf | :propA               |
| :propA-2-1 | rdf:type           | owl:DatatypeProperty |
| :propA-2-1 | rdfs:subPropertyOf | :propA-2             |
| :object1   | :propA-1-1         | "some first value"   |
| :object1   | :propA-2-1         | "some second value"  |
+------------+--------------------+----------------------+

The important thing to note is that you see your TBOX and your DatatypeProperties but if you enable reasoning you don't.

+----------+------------+---------------------+
|    s     |     p      |          o          |
+----------+------------+---------------------+
| :object1 | :propA     | "some first value"  |
| :object1 | :propA     | "some second value" |
| :object1 | :propA-2   | "some second value" |
| :object1 | :propA-1   | "some first value"  |
| :object1 | :propA-1-1 | "some first value"  |
| :object1 | :propA-2-1 | "some second value" |
| :object1 | rdf:type   | owl:Thing           |
+----------+------------+---------------------+

I think they get somehow get pulled into the schema graph which is only accessible to the reasoner and isn't available to queries. If that's the case than the ABOX portion of your query doesn't see anything and you don't get any queries.

To solve this it seems like you want to execute one portion of your query with reasoning and another portion without.

The solution I came up with was to use a service clause. You'll need some setup to get it to work. First you'll need a services.sdpass file in your $STARDOG_HOME. Adding "::*:admin:admin" would work with a default install. Adjust the user name and password for your installation.

The second thing you'll need to do is change the property reasoning.virtual.graph.enabled to false.

Then you should be able to execute your query with reasoning enabled

SELECT ?s ?p ?o WHERE {
	?s ex:propA ?o .
	?s ?p ?o .
    FILTER NOT EXISTS { 
        SERVICE <http://localhost:5820/test/query> {
		?fictiveSubProp rdfs:subPropertyOf ?p .
		FILTER (?p != ?fictiveSubProp)
	 }
   }
}

which returns the expected results

+----------+------------+---------------------+
|    s     |     p      |          o          |
+----------+------------+---------------------+
| :object1 | :propA-1-1 | "some first value"  |
| :object1 | :propA-2-1 | "some second value" |
+----------+------------+---------------------+

Some interesting things I came across while trying to figure this out were. If you enable reasoning over the service clause it fails with

"An unexpected exception was handled by the server
com.stardog.stark.query.QueryExecutionFailure: com.complexible.stardog.plan.eval.ExecutionException: Service clause contains a pattern not supported by reasoning: prefix : <http://api.stardog.com/>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix stardog: <tag:stardog:api:>

Schema(?fictiveSubProp, rdf:type, owl:DatatypeProperty)
`─ {
   `─ Singleton [#1]
   }

NOTE: the ex: prefix isn't there because I made the ex: prefix just :

I also tried it the other way around with reasoning off for the query but enabling reasoning for the service query by making they service query

SERVICE <http:;//localhost:5820/test/query?reasoning=true>

But that failed with the following error

ERROR 2018-12-18 09:59:48,063 [stardog-user-58] com.complexible.stardog.protocols.http.server.StardogHttpServiceLoader:accept(235): An unexpected exception was handled by the server
com.stardog.stark.query.QueryExecutionFailure: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog. [L1:1]

If I were to guess the query is just being concatenated on the end it's blowing up because there's already a parameter on there. Something like http://localhost:5820/test/query?reasoning=true?query=.... but that's just a guess.

This was all done with Stardog 6.0.0 so you might want to upgrade if this doesn't work for you.

Thanks @zachary.whitley for the suggestion. I was hoping for a less hacky, pure SPARQL approach though :confused:

In my implementation, I use a named graph to store the Tbox, so it doesn't clutter my default graph anyhow and it's easier to swap/update pieces of the Tbox. I get the same results there... There should be an easier method to do this kind of queries.

I see your point but to be fair it is pure SPARQL. :grinning:

I suspect that the problem might be with the unbound BGP, ?s ?p ?o so there might be a solution in there more to your liking but my little brain would need a little more time to figure that out.

You might want to try looking at documentation under special predicate

Hi thanks!

By looking into Stardogs syntatic sugar for special predicates, I've found out that (at least in Stardog), every datatype property is a subproperty of owl:bottomDataProperty. The following query returns the most specific datatype property that is used in the graph, but there should not be any other subproperties defined:

PREFIX ex: <http://ex.com/onto#>
SELECT ?s ?p ?o WHERE {
	?s ex:propA ?o .
	?s ?p ?o .
    ### only most specific properties used in the graph
	FILTER NOT EXISTS { 
		?fictiveSubProp rdfs:subPropertyOf ?p .
		FILTER (?p != ?fictiveSubProp) # each property is its own subproperty
        FILTER (?fictiveSubProp != owl:bottomDataProperty) # each property is a subproperty of owl:bottomDataProperty
	}

However, when I also have asserted properties that are not the most precise properties available in the Tbox, the above query will not return them. Then I've found this post on stackoverflow referring to a similar problem when querying for the most specific asserted class while reasoning is used. I modified it and now I always get the most precise property that's available in the graph:

PREFIX ex: <http://ex.com/onto#>
SELECT ?s ?p ?o WHERE {
    ?s ex:propA ?o .
 	?s ?p ?o .
    FILTER NOT EXISTS {
	     ?s ?pOther ?o .
         ?pOther rdfs:subPropertyOf ?p .
         FILTER (?pOther != ?p) # every property is its own subproperty
    }
}

P.S. And apparently as you said, I also don't have to care for which named graph I used to drop the Tbox in, as long as reasoning is turned on. Extra bonus :slight_smile:

Sorry for being late to this. Your last query is indeed correct (possibly one can use sp:strictSubPropertyOf and drop the filter). But in most cases what you're trying to do can be accomplished simply by:

select * { 
  ?s ?p ?o .
  ?p rdfs:subPropertyOf* ex:propA
}

without reasoning. It's pretty rare that your ontology entails sub-property relationships via anything other than rdfs:subPropertyOf axioms. This query will also scale while ?s ?p ?o with query-time reasoning most likely won't.

Cheers,
Pavel

Thanks, that's also a good suggestion. In that case, I need to know the named graph that stores the ontology though, but indeed scales way better.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.