Filter language only if the type is literal - sparql

This is probably almost the same quetion as:
Filter by language only if the object is a literal
Problem is that the answer there doesn't work in my case.
I have this query:
SELECT ?property ?value
WHERE { <http://dbpedia.org/resource/Facebook> ?property ?value
FILTER(STRSTARTS(STR(?property), "http://dbpedia.org/property") || STRSTARTS(STR(?property), "http://dbpedia.org/ontology"))}
Result in Virtuoso
There you would see a list of properties including "alexa rating 2" and "abstract" in many languages.
If I then try the suggested solution in the mentioned question above:
SELECT ?property ?value
WHERE { <http://dbpedia.org/resource/Facebook> ?property ?value
FILTER(STRSTARTS(STR(?property), "http://dbpedia.org/property") || STRSTARTS(STR(?property), "http://dbpedia.org/ontology"))
FILTER(!isLiteral(?value) || langMatches(lang(?value), "EN"))}
Result in Virtuoso
Now you would see that only english version of "abstract" is there but "alexa rating 2" and many other non-string values are gone.
Anyone that knows how to get all properties as in the first query and then for literals only filter out the english language?

Your second query does filter out literals that have a language tag other than English. In RDF 1.0, there are three types of literals:
plain literals (no datatype, and no language tag)
language tagged literals (a string and a language tag)
datatype literals (a lexical form and a datatype)
So the Alexa rating, which has a value of 2, is a literal, and it doesn't have a language tag, so the language tag certainly isn't "EN" (and more importantly, doesn't match "EN"; langMatches does some more complex checks). What you want is to filter out non-English language tagged literals. That's not hard; you just need to add lang(?value) = "" to the filter (since lang returns "" for literals with no language tag):
SELECT ?property ?value
WHERE { <http://dbpedia.org/resource/Facebook> ?property ?value
FILTER(STRSTARTS(STR(?property), "http://dbpedia.org/property") || STRSTARTS(STR(?property), "http://dbpedia.org/ontology"))
FILTER(!isLiteral(?value) || lang(?value) = "" || langMatches(lang(?value), "EN"))}
SPARQL results
The way to read that filter is:
Keep values that
are not literals; or
are literals, but don't have a language tag; or
are literals with a language tag that matches "en".

So it sounds like you simply want to invert the filter condition on the language right?
In which case you simply need to invert the langMatches call by adding a ! before it i.e. adding the not operator to it:
SELECT ?property ?value
WHERE { <http://dbpedia.org/resource/Facebook> ?property ?value
FILTER(STRSTARTS(STR(?property), "http://dbpedia.org/property") || STRSTARTS(STR(?property), "http://dbpedia.org/ontology"))
FILTER(!isLiteral(?value) || !langMatches(lang(?value), "EN"))}
Result in DBPedia
With this simple change the English entries are now eliminated and I see only the non-English entries.

Related

How can I use SPARQL to find instances where two properties do not share any of the same objects?

In my company's taxonomy, all concepts have a value for skos:prefLabel, and most have a bunch of values for a custom property -- let's call it ex:keyword -- whose values have the datatype rdf:langString. I want to find concepts where the value of skos:prefLabel does NOT exactly match ANY value of ex:keyword, when case and language are ignored.
It is fairly straightforward to write a query for concepts where the values DO match, like this:
SELECT *
WHERE {
?concept skos:prefLabel ?label ;
ex:keyword ?kw
FILTER (lcase(str(?label)) = lcase(str(?kw)))
}
Where I'm getting tripped up is in trying to negate this.
Using != in the FILTER would just return a bunch of cases where ?label and ?kw don't match, which is not what I'm after.
What I would like is to be able to use a FILTER NOT EXISTS, but that's invalid with an expression like (?a = ?b); it only works with something like {?a ?b ?c}.
I suspect that there is a proper way to express FILTER NOT EXISTS (?a = ?b) in SPARQL, but I don't know what it is. Can someone help?
The trick is to put the triple pattern for matching the keyword in the FILTER NOT EXISTS, like so:
SELECT *
WHERE {
?concept skos:prefLabel ?label .
FILTER NOT EXISTS { ?concept ex:keyword ?kw .
FILTER(lcase(str(?label)) = lcase(str(?kw)))
}
}
This query says "I want all concepts with a preflabel such that the concept has no keyword value that matches that prefLabel".

SPARQL Filter language for only one property

SELECT ?pt ?vl
WHERE {<http://dbpedia.org/resource/Havana_Storm> ?pt ?vl.}
My query will return list of property-value pairs of this book; but with the "abstract" property, I only want to take English language. How can I do it?
This filters all values to the English language.
SELECT ?pt ?vl
WHERE {
<http://dbpedia.org/resource/Havana_Storm> ?pt ?vl.
FILTER(LANG(?vl) = "en")
}
SPARQL Query

SPARQL list literals of selected OWL Datatype

How to list all literals of only selected OWL datatype (here :VisibilityKind) in SPARQL? The OWL datatype definition of VisibilityKind is:
DatatypeDefinition( :VisibilityKind
DataOneOf( "public"^^xsd:string "private"^^xsd:string "package"^^xsd:string )
)
With SPARQL, you can get all the literals that have a certain datatype IRI. For instance, assuming you have data with literals such as "public"^^:VisibilityKind, you can write:
SELECT ?literal WHERE {
?s ?p ?literal .
FILTER (datatype(?literal) = :VisibilityKind)
}
But this is certainly not what you want because you probably do not have literals with this datatype IRI. What you would probably like is something that could roughly be formulated as:
SELECT ?literal WHERE {
?s ?p ?literal .
FILTER (isInDatatype(?literal,:VisibilityKind))
}
where isInDatatype checks if the value associated with ?o belongs to the value space of :VisibilityKind. However, such function does not exist in standard SPARQL 1.1. Moreover, even if it existed, it would require the query engine to understand the semantics of OWL 2 and do reasoning. So you would need a SPARQL engine that implements the OWL 2 DL entailment regime and you'd have to hack a bit the query to get what you want:
SELECT ?literal WHERE {
?s ?p ?literal .
[] a :VisibilityKind;
:owl:sameAs ?literal;
FILTER (isLiteral(?literal))
}
If you want to find implementations of SPARQL 1.1 Entailment regimes, you could take a look at the implementation reports collected by the SPARQL working group.
To answer directly, you need to search for all values in the owl:oneOf list:
SELECT ?resource ?value
WHERE {
:VisibilityKind owl:equivalentClass / owl:oneOf / ( rdf:rest*/rdf:first ) ?value .
?resource ?prop ?value .
}
However, there is a caveat - other properties could have the value "public" "private" or "package". To ensure that you're getting only the values of :VisibilityKind, define that datatype as a range of properties that use the datatype:
{ :someProp rdfs:domain :VisibilityKind }
Then use the following query to get all properties that define :VisibilityKind in the range:
SELECT ?resource ?value
WHERE {
?prop rdfs:range :VisibilityKind .
?resource ?prop ?value
}

How to check prefix of variables in SPARQL?

I want to find how many resource is there in an RDF but I can't find any tutorial to explain how can I check the prefix of variables in my SPARQL.
I have tried this:
select count(?x) where {
res:?x ?p ?v
}
but it has syntax error. I am using virtuoso for DBPedia
You can use strstarts(string,prefix) to check whether string begins with prefix. You can use the str function to get the string representation of a IRI, including IRIs generated from prefixes. E.g., if you have prefix ex: <http://example.org/>, then ex: by itself is a legal IRI, and str(ex:) produces "http://example.org/". That means that you can check whether an IRI that is the value of a variable ?x begins with some particular prefix p: by doing strstarts(str(?x),str(p:)). Then you can filter on that, or count it, etc.
Here's an example that binds ?thing to a few different values, some of which begin with the dbpedia-owl: prefix:
select * where {
values ?thing { dbpedia-owl:a dbpedia-owl:b dbpprop:c }
bind( strstarts(str(?thing),str(dbpedia-owl:)) as ?startsWithDBpediaOwl )
}
SPARQL results (a and b get true, c gets false)
You can filter on that too, and then count the results:
select (count(*) as ?n) where {
values ?thing { dbpedia-owl:a dbpedia-owl:b dbpprop:c }
filter strstarts(str(?thing),str(dbpedia-owl:))
}
SPARQL results (2)

How do i make sparql query only about data type name?

How to display data's property label?
I working for dbpedia ontology,
I want to make a sparql query, below is my sample query. This result is mix up either datatype or object type, I want to datatype property name.
SELECT ?p ?pLabel ?domain ?range
{
?p rdfs:domain http://dbpedia.org/ontology/Person> .
}
ex: Following is data type example, but I cannot select only datatype, I want to display
type name.
"chat"
'chat'#fr with language tag "fr"
"xyz"^^<http://example.org/ns/userDatatype>
"abc"^^appNS:appDataType
'''The librarian said, "Perhaps you would enjoy 'War and Peace'."'''
1, which is the same as "1"^^xsd:integer
1.3, which is the same as "1.3"^^xsd:decimal
1.300, which is the same as "1.300"^^xsd:decimal
1.0e6, which is the same as "1.0e6"^^xsd:double
true, which is the same as "true"^^xsd:boolean
false, which is the same as "false"^^xsd:boolean
expect to result
Expect to result (only data type)
typename <- field name
string <- type name
int
boolean
int
double
boolean
How to make a sparql query?
Use function datatype() for that purpose. For example:
select distinct ?y datatype(?z)
{
?x a <http://dbpedia.org/class/yago/JeskolaBuzzUsers>.
?x ?y ?z.
filter (datatype(?z) != '')
}
PREFIX xsd: http://www.w3.org/2001/XMLSchema#
ASK WHERE
{
?item dm:amount ?amount .
FILTER ((datatype(?amount)) != xsd:integer)
}
The query engine still knew which ?amount values were integers and which were not,
because any unquoted series of digits with no period is treated as an integer.
Most of your work with datatypes in SPARQL will involve the use of functions that are
covered in more detail in the next section. Before we look at any of those, it’s a good
idea to know how representations of typed literals in your queries interact with different
kinds of literals in your dataset.