I need some help starting with SPARQL:
I have some individuals (A, B, C). I want to state, that they are all the same. I’ve tried the following:
PREFIX : <http://test.com#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
CONSTRUCT {
?p owl:sameAs ?p
}
WHERE {
} VALUES (?p) {
(:A)
(:B)
(:C)
}
The result is:
:B owl:sameAs :B .
:A owl:sameAs :A .
:C owl:sameAs :C .
What I would like to have is something like this:
:A owl:sameAs :B
:A owl:sameAs :C
:B owl:sameAs :A
:B owl:sameAs :C
:C owl:sameAs :A
:C owl:sameAs :B
Do you have any hints for me, how to do that?
Related
I have a number of triples organized like following.
:A :hasB :B
:B :hasC :C
:C :hasD :D
:D :hasE :E
............
:X :hasY :Y
:Y :hasZ :Z
All the predicates are unique.
I need to write two SPARQL queries.
Query 1 will find all the predicates between :A to :Z through a transitive query (something like this :A :has* :Z). Output 1 should look like following.
Output 1:
--------
hasB
hasC
hasD
....
hasZ
Ouery 2 will find triples between :A to :Z through a transitive query. Output 2 should look like following.
Output 2:
--------
:B :hasC :C
:C :hasD :D
:D :hasE :E
............
:X :hasY :Y
Please let me know how to write these transitive SPARQL queries.
SPARQL has some obvious limitations as it's not a graph query language. Possible solutions below:
If there are no other predicates besides has[A-Z]:
Sample Data
#prefix : <http://ex.org/> .
:A :hasB :B .
:B :hasC :C .
:C :hasD :D .
:D :hasE :E .
Query
prefix : <http://ex.org/>
select ?p
where {
values (?start ?end) { (:A :E) }
?start (<p>|!<p>)* ?v1 .
?v1 ?p ?v2 .
?v2 (<p>|!<p>)* ?end .
}
Output
---------
| p |
=========
| :hasB |
| :hasC |
| :hasD |
| :hasE |
---------
If there are other predicates besides has[A-Z]:
Sample Data
#prefix : <http://ex.org/> .
:A :hasB :B .
:B :hasC :C .
:C :hasD :D .
:C :notHasD :D .
:D :hasE :E .
Introduce a super property :has:
Additional Data:
#prefix : <http://ex.org/> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
:hasB rdfs:subPropertyOf :has .
:hasC rdfs:subPropertyOf :has .
:hasD rdfs:subPropertyOf :has .
:hasE rdfs:subPropertyOf :has .
Query:
prefix : <http://ex.org/>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select ?p
where {
values (?start ?end) { (:A :E) }
?start (<p>|!<p>)* ?v1 .
?v1 ?p ?v2 . ?p rdfs:subPropertyOf :has .
?v2 (<p>|!<p>)* ?end .
}
Output
---------
| p |
=========
| :hasB |
| :hasC |
| :hasD |
| :hasE |
---------
Use REGEX on property URI:
prefix : <http://ex.org/>
select ?p
where {
values (?start ?end) { (:A :E) }
?start (<p>|!<p>)* ?v1 .
?v1 ?p ?v2 .
FILTER(REGEX(STRAFTER(STR(?p), STR(:)), 'has[A-Z]'))
?v2 (<p>|!<p>)* ?end .
}
Note, all the proposed solutions will not work on all kind of data, especially once you have multiple paths and/or cycles. In that case, you should use a proper graph database.
This is my query
PREFIX : <http://example.org/rs#>
select ?item (SUM(?similarity) as ?summedSimilarity)
(group_concat(distinct ?becauseOf ; separator = " , ") as ?reason) where
{
values ?x {:instance1}
{
?x ?p ?instance.
?item ?p ?instance.
?p :hasSimilarityValue ?similarity
bind (?p as ?becauseOf)
}
union
{
?x a ?class.
?item a ?class.
?class :hasSimilarityValue ?similarity
bind (?class as ?becauseOf)
}
filter (?x != ?item)
}
group by ?item
in my firstbind clause, I would like to not just bind the variable ?p, but also the variable ?instance. Plus, adding a text like that is why.
so the first bind should result the following results:
?p that is why ?instance
is that possible in SPARQL ?
please don't care about if the data makes sence or not, it is just a query to show you my question
If I understand you correctly, you're just looking for the concat function. As I've mentioned before, you should really browse through the SPARQL 1.1 standard, at least through the table of contents. You don't need to memorize it, but it will give you an idea of what things are possible, and an idea of where to look. Additionally, it's very helpful if you provide sample data that we can work with, because it makes it much clearer to figure out what you're trying to do. The phrasing of your title was not particularly clear, and the question doesn't really provide an example of what you're trying to accomplish. Only because I've seen some of your past questions did I have an idea of what you were aiming for. At any rate, here's some data:
#prefix : <urn:ex:>
:p :hasSimilarity 0.3 .
:A :hasSimilarity 0.6 .
:a :p :b ; #-- is is related to :b
a :A . #-- and is an :A .
:c :p :b . #-- :c is also related to :b
:d a :A . #-- :d is also an :A .
:e :p :b ; #-- :e is related to :b
a :A . #-- and is also an :A .
And here's the query and its results. You just use concat to join the str form of your variables with the appropriate strings and then bind the result to the variable.
prefix : <urn:ex:>
select ?item
(sum(?factor_) as ?factor)
(group_concat(distinct ?reason_; separator=", ") as ?reason)
{
values ?x { :a }
{ ?x ?p ?instance .
?item ?p ?instance .
?p :hasSimilarity ?factor_ .
bind(concat("has common ",str(?p)," value ",str(?instance)) as ?reason_) }
union
{ ?x a ?class.
?item a ?class.
?class :hasSimilarity ?factor_ .
bind(concat("has common class ",str(?class)) as ?reason_)
}
filter (?x != ?item)
}
group by ?item
-----------------------------------------------------------------------------------
| item | factor | reason |
===================================================================================
| :c | 0.3 | "has common urn:ex:p value urn:ex:b" |
| :d | 0.6 | "has common class urn:ex:A" |
| :e | 0.9 | "has common urn:ex:p value urn:ex:b, has common class urn:ex:A" |
-----------------------------------------------------------------------------------
Using the following sample triples:
#prefix : <http://www.me.org/me_schema#> .
#prefix dc: <http://purl.org/dc#> .
#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 skos: <http://www.w3.org/2004/02/skos/core#> .
#prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
<http://www.me.org/content/me_schema>
rdf:type owl:Ontology ;
owl:imports <http://www.w3.org/2004/02/skos/core> ;
.
:a
rdf:type owl:ObjectProperty ;
rdfs:label "A" ;
rdfs:subPropertyOf :b ;
.
:b
rdf:type owl:ObjectProperty ;
rdfs:label "B" ;
rdfs:subPropertyOf :c ;
.
:c
rdfs:label "C"^^xsd:string ;
.
This query returns two rows as expected (both b and c in column ?o):
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select *
from <test>
where
{
?s rdfs:label 'A' .
?s rdfs:subPropertyOf+ ?o
}
However, I expect the following to return 1 row but it returns empty result. Tested in query console:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select *
from <test>
where
{
?s rdfs:label 'A' .
?s rdfs:subPropertyOf+ <http://www.me.org/me_schema#c>
}
I expect that it returns one row for "a". Is this a bug or am I missing something obvious?
I tried a similar query with DBPedia and it appears to return data as I expected. For example, the following query returns two rows for "star" although neither are direct subClassOf owl:Thing.
select *
where
{
?s rdfs:label "star"#en .
?s rdfs:subClassOf+ owl:Thing
} LIMIT 100
I came up with the following work around in case anyone is having same problem:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select *
from <test>
where
{
?s rdfs:label 'A' .
?s rdfs:subPropertyOf ?s2 .
?s2 rdfs:subPropertyOf* <http://www.me.org/me_schema#c>
}
(I would put this in a comment, but I don't have the reputation needed to do that.)
I just tried your null-result example on MarkLogic 8.0-3, and I do indeed get [{"s":"<http://www.me.org/me_schema#a>"}], as you expected. Are you using an earlier version of MarkLogic (you can see the version in the upper-left corner of localhost:8001)?
To verify this, I went to the MarkLogic query console at localhost:8000/qconsole/, set the 'Content Source' to my database (with the triple index turned on) changed the query type to 'SPARQL Update', and entered this SPARQL insert code:
PREFIX : <http://www.me.org/me_schema#>
prefix dc: <http://purl.org/dc#>
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 skos: <http://www.w3.org/2004/02/skos/core#>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
INSERT DATA { GRAPH <test> {
<http://www.me.org/content/me_schema> rdf:type owl:Ontology .
<http://www.me.org/content/me_schema> owl:imports <http://www.w3.org/2004/02/skos/core> .
:a rdf:type owl:ObjectProperty .
:a rdfs:label "A" .
:a rdfs:subPropertyOf :b .
:b rdf:type owl:ObjectProperty .
:b rdfs:label "B" .
:b rdfs:subPropertyOf :c .
:c rdfs:label "C"^^xsd:string .
}}
I then opened a new tab within the Query Console, set the Query Type to "SPARQL Query", and ran your exact query:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select *
from <test>
where
{
?s rdfs:label 'A' .
?s rdfs:subPropertyOf+ <http://www.me.org/me_schema#c>
}
If you are using an earlier version of MarkLogic, try updating to the latest on the MarkLogic download page.
I have an ontology that defines a new data type as pattern restriction on string type. This data type is then used as a property range restriction. Then a class is defined as a restriction on this property:
#prefix : <http://test.com/prop#> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix xml: <http://www.w3.org/XML/1998/namespace> .
#prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
#base <http://test.com/prop> .
<http://test.com/prop> rdf:type owl:Ontology .
:MyType rdf:type rdfs:Datatype ;
owl:equivalentClass [ rdf:type rdfs:Datatype ;
owl:onDatatype xsd:string ;
owl:withRestrictions ( [ xsd:pattern "[a-zA-Z]*"
]
)
] .
# Properties
:hasProperty rdf:type owl:ObjectProperty .
:hasValue rdf:type owl:DatatypeProperty .
# Classes
:BaseClass rdf:type owl:Class .
:BaseProperty rdf:type owl:Class .
:MyClass rdf:type owl:Class ;
owl:equivalentClass [ rdf:type owl:Class ;
owl:intersectionOf ( :BaseClass
[ rdf:type owl:Restriction ;
owl:onProperty :hasProperty ;
owl:someValuesFrom :MyProperty
]
)
] ;
rdfs:subClassOf :BaseClass .
:MyProperty rdf:type owl:Class ;
owl:equivalentClass [ rdf:type owl:Class ;
owl:intersectionOf ( :BaseProperty
[ rdf:type owl:Restriction ;
owl:onProperty :hasValue ;
owl:someValuesFrom :MyType
]
)
] ;
rdfs:subClassOf :BaseProperty .
# Individuals
:Ind1 rdf:type :BaseClass ,
owl:NamedIndividual ;
:hasProperty :Prop1 .
:Prop1 rdf:type :BaseProperty ,
owl:NamedIndividual ;
:hasValue "Maier" .
The Protege crashes while classifying this ontology with Pellet reasoner:
UnsupportedOperationException: null
com.clarkparsia.pellet.datatypes.types.text.RestrictedTextDatatype.applyConstrainingFacet(RestrictedTextDatatype.java:93)
com.clarkparsia.pellet.datatypes.DatatypeReasonerImpl.getDataRange(DatatypeReasonerImpl.java:440)
The FaCT++ reasoner failed with exception:
ReasonerInternalException: Unsupported datatype 'http://test.com/prop#MyType'
uk.ac.manchester.cs.factplusplus.FaCTPlusPlus.getBuiltInDataType(Native Method)
The Pellet seems only to have trouble with the pattern as a restriction. The FaCT++ seems to have trouble with a user defined datatype.
Do I have errors in the ontology or the reasoners are not able to classify such pattern restriction?
The current version of FaCT++ does not support user-defined datatypes. So the report from FaCT++ is correct.
Pellet should support user-defined datatypes, but your definition is incorrect. The owl:equivalentClass construction is a) from the obsolete OWL 1 syntax, that doesn't support datatype definitions, and b) is only valid for classes, not datatypes. I would suggest to use OWL 2 syntax http://www.w3.org/TR/2012/REC-owl2-syntax-20121211/ in your datatype definition.
Take this graph:
:thing1 a :Foo ;
:has :A ;
:has :B .
:thing2 a :Foo ;
:has :B ;
:has :A .
:thing3 a :Foo ;
:has :A ;
:has :B ;
:has :C .
I want to select :thing1 and :thing2, but NOT :thing3.
Here is the SPARQL query I wrote that works. Is there a better way to do this?
SELECT ?foo WHERE {
?foo a :Foo ;
:has :A ;
:has :B .
MINUS {
?foo a :Foo ;
:has :A ;
:has :B ;
:has ?anythingElse .
FILTER(?anythingElse != :A && ?anythingElse != :B)
}
}
An alternative to MINUS is FILTER NOT EXISTS:
SELECT ?foo WHERE {
?foo a :Foo ;
:has :A, :B .
FILTER NOT EXISTS {
?foo :has ?other .
FILTER (?other NOT IN (:A, :B))
}
}
which says, loosely, find all ?foo with :A and :B, then check that they have no other :has value.
In terms of execution efficiency, there are optimizations to turn some MINUS patterns into FILTER NOT EXISTS and vice versa and also there is the possibility of shared common sub patterns.
Without an optimizer being that smart, the FILTER NOT EXISTS is likely to be faster because the "?foo a :Foo ; ;has :A, :B ." is not repeated and the FILTER only considers items that already passed the "?foo a :Foo ; ;has :A, :B .".
There is only one way to know which is to try for real on real data when all effects, including caching, come together.
You can do this using using the NOT IN operator instead of a boolean expression, and indeed there is no need to repeat the three triple patterns if you replace the MINUS clause with a FILTER NOT EXISTS clause:
SELECT ?foo WHERE {
?foo a :Foo ;
:has :A, :B .
FILTER NOT EXISTS {
?foo :has ?other .
FILTER (?other NOT IN (:A, :B))
}
}
I doubt there'll be a significant difference in performance, but the query is shorter and easier to read.