Background
I have a graph database where nodes represent individual people and the edges are predicates hasMother and hasFather. I'd like to identify all of the nodes that share a mother, but don't share the same father.
Attempt
There are a few SPARQL terms that immediately pop into my mind when thinking about this problem. Namely Filter, != and NOT EXISTS.
I first set out and defined some sets...
Let M be the set of all winiks that have mother id, mother_id.
Let F be the set of all winiks that have father id, father_id.
The following query returns a qraph of M ∩ F.
PREFIX ex: <https://ex.com#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
CONSTRUCT WHERE {
?winik_id ex:hasMother ?mother_id.
?winik_id ex:hasFather ?father_id.
}
My hiccup is writing the exclusion part (its actually hard for me to verbalize the exact part I'm stuck on)-specifically how to deal with how general the query is (across all identifiers).
This should return pairs of people that have the same mother but different father.
SELECT ?p1 ?p2 WHERE {
?p1 ex:hasMother ?m .
?p1 ex:hasFather ?f .
?p2 ex:hasMother ?m .
?p2 ex:hasFather ?f2 .
FILTER (?f != ?f2)
Related
I have a specific instance and a SPARQL query that retrieves other instances similar to that one. By similar, I mean that the other instances have at least one common property and value in common with the specific instance, or have a class in common with the specific instance.
Now, I'd like to extend the query such that if the specific instance has a value for a "critical" property, then the only instances that are considered similar are those that also have that critical property (as opposed to just having at least one property and value in common).
For instance, here is some sample data in which instance1 has a value for predicate2 which is a subproperty of isCriticalPredicate.
#prefix : <http://example.org/rs#>
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
:instance1 a :class1.
:instance1 :predicate1 :instance3.
:instance1 :predicate2 :instance3. # (#) critical property
:instance2 a :class1.
:instance2 :predicate1 :instance3.
:instance4 :predicate2 :instance3.
:predicate1 :hasSimilarityValue 0.6.
:predicate2 rdfs:subPropertyOf :isCriticalPredicate.
:predicate2 :hasSimilarityValue 0.6.
:class1 :hasSimilarityValue 0.4.
Here is a query in which ?x is the specific instance, instance1. The query retrieves just instance4, which is correct. However, if I remove the critical property from instance1 (line labeled with #), I get no results, but should get instance2, since it has a property in common with instance1. How can I fix this?
PREFIX : <http://example.org/rs#>
select ?item (SUM(?similarity * ?importance * ?levelImportance) as ?summedSimilarity)
(group_concat(distinct ?becauseOf ; separator = " , ") as ?reason) where
{
values ?x {:instance1}
bind (4/7 as ?levelImportance)
{
values ?instanceImportance {1}
?x ?p ?instance.
?item ?p ?instance.
?p :hasSimilarityValue ?similarity
bind (?p as ?becauseOf)
bind (?instanceImportance as ?importance)
}
union
{
values ?classImportance {1}
?x a ?class.
?item a ?class.
?class :hasSimilarityValue ?similarity
bind (?class as ?becauseOf)
bind (?classImportance as ?importance)
}
filter (?x != ?item)
?x :isCriticalPredicate ?y.
?item :isCriticalPredicate ?y.
}
group by ?item
I've said it before and I'll say it again: minimal data is very helpful. From your past questions, I know that your working project has similarity values on properties and the like, but none of that really matters for the problem at hand. Here's some data that just has a few instances, property values, and one property designated as critical:
#prefix : <urn:ex:>
:p a :criticalProperty .
:a :p :u ; #-- :a has a critical property, so
:q :v . #-- only :d can be similar to it.
:c :q :v ; #-- :c has no critical properties, so
:r :w . #-- both :a and :d can be similar to it.
:d :p :u ;
:q :v .
The trick in a query like this is to filter out the results that have the problem, not to try to select the ones that don't. Logically, those mean the same thing, but in writing the query, it's easier to think about constraint violation, and to try to filter out the results that violate the constraint. In this case, you want to filter out any results where the instance has a critical property and value but the similar instance doesn't.
prefix : <urn:ex:>
select ?i (group_concat(distinct ?j) as ?js) where {
#-- :a has a critical property, but
#-- :c does not, so these are useful
#-- starting points
values ?i { :a :c }
#-- get ?j instances that have a value
#-- in common with ?i.
?i ?property ?value .
?j ?property ?value .
#-- make sure that ?i and ?j aren't
#-- the same instance
filter (?i != ?j)
#-- make sure that there is no critical
#-- property value that ?i has that
#-- ?j does not also have
filter not exists {
?i ?criticalProperty ?criticalValue .
?criticalProperty a :criticalProperty .
filter not exists {
?j ?criticalProperty ?criticalValue .
}
}
}
group by ?i
----------------------------
| i | js |
============================
| :a | "urn:ex:d" |
| :c | "urn:ex:d urn:ex:a" |
----------------------------
Related
There are some other questions that also touch on constaint satisfaction/violation that might be useful reading. While not all of these use nested filter not exists, most of them do have a pattern of filter not exists { … filter <negative condition> }.
Find lists containing ALL values in a set? (This actually uses a nested filter not exists.)
Is it possible to express a recursive definition in SPARQL?
Count values that satisfy a constraint and return 0 for those that don't satisfy it in SPARQL
SPARQL: return all intersections fulfilled by specified or equivalent classes (There's another nested filter not exists, in the last query in the answer.)
In my data there are two triples:
entity1 doA entity2 .
entity2 doB entity3 .
I am looking for a way to infer the following triple and have it back in the outcome of my SPARQL query (e.g., select ?a ?c {?a doC ?c)) :
entity1 doC entity3 .
Basically, I want to say:
IF (?a doA ?b) and (?b doB ?c) THEN (?a doC ?c)
Note, I am looking for a solution that can be completely implemented using the AGWebView interface.
If AllegroGraph supports SPARQL 1.1m then you could try:
INSERT {?a <doC> ?c}
WHERE {
?a <doA> ?b .
?b <doB> ?c .
}
That inserts into the default graph, however that is defined. To direct to a specific graph, then add a GRAPH statement to the insert:
INSERT { GRAPH <graph-uri> {
?a <doC> ?c}
}
...
Any help in my learning will be highly appreciated.
Problem statement:
Need to print list of tourist places in various cities
I have http://dbpedia.org/page/Category:Tourism_by_city category which i have to explore. The problem is this category is a skos:broader of various other categories like http://dbpedia.org/page/Category:Tourism_in_Bratislava which in itself is a skos:broader of http://dbpedia.org/page/Category:Visitor_attractions_in_Bratislava which contains dcterms:subject property and which is the list of tourist places.
I have to explore all cities starting from Tourism_by_city category.
What I have done
SELECT DISTINCT ?places
WHERE {
?entity skos:broader* <http://dbpedia.org/resource/Category:Tourism_by_city> .
?places dcterms:subject ?entity
}
Problem:
skos:broader is further exploring the graph, i want to restrict it till Visitor_attractions level. Also skos:broader is exploring all the categories but i want it to explore for just Visitor_attractions category.
Level 1 : Tourism_by_city - > explore all skos:broader of
Level 2 : Tourism_by_xxxcity -> explore only category:Vistors_attractions_by_xxxcity
Level 3 : Do not explore further.
Is this achievable ?
Please do let me know if question is unclear. Thanks
Finally solved the question, I don't know whether this is the only viable option:
SELECT DISTINCT (str(?city) as ?City) (str(?label) as ?Attractions)
WHERE {
?entity skos:broader <http://dbpedia.org/resource/Category:Tourism_by_city> .
?places skos:broader ?entity .
?places rdfs:label ?city .
FILTER langMatches(lang(?city),"en") .
?attractions dcterms:subject ?places .
?attractions rdfs:label ?label .
FILTER langMatches(lang(?label),"en").
FILTER (if (isliteral(?city ), contains(str(?city ), "Visitor"), false))
}
ORDER BY ASC(?city)
I am trying to collect the list of landmarks listed in Wikipedia per country, for example US Landmarks . But this parent Category just includes subcategories and It is not clear how many layers one has to go down to get to the actual data. Is there any way to make a SPARQL query for something like that? Or is there any other way to do it?
Simple queries like this returns nothing
SELECT DISTINCT ?namedEnt WHERE {?namedEnt <http://purl.org/dc/terms/subject> <http://dbpedia.org/resource/Category:Category:Landmarks_in_the_United_States_by_state>} limit 10
It seems relationship between sucategory and its parent category is represented using skos:broader in DBpedia. If you combine that with *, which represents one or more applications of a predicate, the query becomes:
PREFIX cat: <http://dbpedia.org/resource/Category:>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
SELECT DISTINCT ?page
WHERE {
?subcat skos:broader* cat:Landmarks_in_the_United_States_by_state.
?page dcterms:subject ?subcat
}
Or you can shorten it using / to just:
SELECT DISTINCT ?page
WHERE {
?page dcterms:subject/skos:broader* cat:Landmarks_in_the_United_States_by_state
}
Is it possible to have a definition of an resource (from DBpedia) with a SPARQL query? I want to have something like the TBox and ABox that are shown in (Conceptual) Clustering methods for
the Semantic Web: issues and applications (slides 10–11). For example, for DBpedia resource Stephen King, I would like to have:
Stephen_King : Person ⊓ Writer ⊓ Male ⊓ … (most specific classes)
You can use a query like the following to ask for the classes of which Stephen King is an instance which have no subclasses of which Stephen King is also an instance. This seems to align well with the idea of “most specific classes.” However, since (as far as I know) there's no reasoner attached to the DBpedia SPARQL endpoint, there may be subclass relationships that could be inferred but which aren't explicitly present in the data.
select distinct ?type where {
dbr:Stephen_King a ?type .
filter not exists {
?subtype ^a dbr:Stephen_King ;
rdfs:subClassOf ?type .
}
}
SPARQL results
Actually, since every class is an rdfs:subClassOf itself, you might want to add another line to that query to exclude the case where ?subtype and ?type are the same:
select distinct ?type where {
dbr:Stephen_King a ?type .
filter not exists {
?subtype ^a dbr:Stephen_King ;
rdfs:subClassOf ?type .
filter ( ?subtype != ?type )
}
}
SPARQL results
If you actually want a result string like the one shown in those slides, you could use values to bind a variable to dbr:Stephen_King, and then use some grouping and string concatenation to get something nicer looking (sort of):
select
(concat( ?person, " =\n", group_concat(?type; separator=" AND\n")) as ?sentence)
where {
values ?person { dbr:Stephen_King }
?type ^a ?person .
filter not exists {
?subtype ^a ?person ;
rdfs:subClassOf ?type .
filter ( ?subtype != ?type )
}
}
group by ?person
SPARQL results
http://dbpedia.org/resource/Stephen_King =
http://dbpedia.org/class/yago/AuthorsOfBooksAboutWritingFiction AND
http://dbpedia.org/ontology/Writer AND
http://schema.org/Person AND
http://xmlns.com/foaf/0.1/Person AND
http://dbpedia.org/class/yago/AmericanSchoolteachers AND
http://dbpedia.org/class/yago/LivingPeople AND
http://dbpedia.org/class/yago/PeopleFromBangor,Maine AND
http://dbpedia.org/class/yago/PeopleFromPortland,Maine AND
http://dbpedia.org/class/yago/PeopleFromSarasota,Florida AND
http://dbpedia.org/class/yago/PeopleSelf-identifyingAsAlcoholics AND
http://umbel.org/umbel/rc/Artist AND
http://umbel.org/umbel/rc/Writer AND
http://dbpedia.org/class/yago/20th-centuryNovelists AND
http://dbpedia.org/class/yago/21st-centuryNovelists AND
http://dbpedia.org/class/yago/AmericanHorrorWriters AND
http://dbpedia.org/class/yago/AmericanNovelists AND
http://dbpedia.org/class/yago/AmericanShortStoryWriters AND
http://dbpedia.org/class/yago/CthulhuMythosWriters AND
http://dbpedia.org/class/yago/HorrorWriters AND
http://dbpedia.org/class/yago/WritersFromMaine AND
http://dbpedia.org/class/yago/PeopleFromDurham,Maine AND
http://dbpedia.org/class/yago/PeopleFromLisbon,Maine AND
http://dbpedia.org/class/yago/PostmodernWriters