Retrieving the wider dbpedia vocabulary for tagging pictures - sparql

I'm trying to develop a tool in JS for tagging pictures, so I need a set of possible "things" from dbpedia. I already tryed to retrieve this way:
select ?s ?l {
?s a owl:Class .
?s rdf:type ?l
FILTER regex(str(?s), "House", "i").
}
http://dbpedia.org/snorql/?query=select+%3Fs+%3Fl+%7B%0D%0A+++%3Fs+a+owl%3AClass+.%0D%0A+++%3Fs+rdf%3Atype+%3Fl%0D%0A+++FILTER+regex%28str%28%3Fs%29%2C+%22House%22%2C+%22i%22%29.%0D%0A%7D
And also this way:
select ?label
WHERE {
?concept a skos:Concept.
?concept skos:prefLabel ?label.
FILTER regex(str(?label), "^House", "i").
}
http://dbpedia.org/snorql/?query=select+%3Flabel+%0D%0AWHERE+%7B%0D%0A++%3Fconcept+a+skos%3AConcept.%0D%0A++%3Fconcept+skos%3AprefLabel+%3Flabel.%0D%0A++FILTER+regex%28str%28%3Flabel%29%2C+%22%5EHouse%22%2C+%22i%22%29.%0D%0A%7D
In the first case, I just have "instances" of the house "thing", but not the "House" class itself. In the second one, I never retrieve the "house" and the similar thing is "houses". Any alternative for retrieving a better vocabulary based in dbpedia dataset?

If you don't bother to restrict yourself to owl:Thing or to skos:Concept, you can just get things that have a label that contains "house". Rather than using regex, I chose to use contains and lcase, since a string containment could be less expensive than invoking a full regular expression processor.
select ?thing ?label where {
?thing rdfs:label ?label .
filter contains(lcase(?label), "house")
}
SPARQL results (limited to 200)

Related

How to find relations/properties for SPARQL queries [duplicate]

whenever I start using SQL I tend to throw a couple of exploratory statements at the database in order to understand what is available, and what form the data takes.
e.g.
show tables
describe table
select * from table
Could anyone help me understand the way to complete a similar exploration of an RDF datastore using a SPARQL endpoint?
Well, the obvious first start is to look at the classes and properties present in the data.
Here is how to see what classes are being used:
SELECT DISTINCT ?class
WHERE {
?s a ?class .
}
LIMIT 25
OFFSET 0
(LIMIT and OFFSET are there for paging. It is worth getting used to these especially if you are sending your query over the Internet. I'll omit them in the other examples.)
a is a special SPARQL (and Notation3/Turtle) syntax to represent the rdf:type predicate - this links individual instances to owl:Class/rdfs:Class types (roughly equivalent to tables in SQL RDBMSes).
Secondly, you want to look at the properties. You can do this either by using the classes you've searched for or just looking for properties. Let's just get all the properties out of the store:
SELECT DISTINCT ?property
WHERE {
?s ?property ?o .
}
This will get all the properties, which you probably aren't interested in. This is equivalent to a list of all the row columns in SQL, but without any grouping by the table.
More useful is to see what properties are being used by instances that declare a particular class:
SELECT DISTINCT ?property
WHERE {
?s a <http://xmlns.com/foaf/0.1/Person>;
?property ?o .
}
This will get you back the properties used on any instances that satisfy the first triple - namely, that have the rdf:type of http://xmlns.com/foaf/0.1/Person.
Remember, because a rdf:Resource can have multiple rdf:type properties - classes if you will - and because RDF's data model is additive, you don't have a diamond problem. The type is just another property - it's just a useful social agreement to say that some things are persons or dogs or genes or football teams. It doesn't mean that the data store is going to contain properties usually associated with that type. The type doesn't guarantee anything in terms of what properties a resource might have.
You need to familiarise yourself with the data model and the use of SPARQL's UNION and OPTIONAL syntax. The rough mapping of rdf:type to SQL tables is just that - rough.
You might want to know what kind of entity the property is pointing to. Firstly, you probably want to know about datatype properties - equivalent to literals or primitives. You know, strings, integers, etc. RDF defines these literals as all inheriting from string. We can filter out just those properties that are literals using the SPARQL filter method isLiteral:
SELECT DISTINCT ?property
WHERE {
?s a <http://xmlns.com/foaf/0.1/Person>;
?property ?o .
FILTER isLiteral(?o)
}
We are here only going to get properties that have as their object a literal - a string, date-time, boolean, or one of the other XSD datatypes.
But what about the non-literal objects? Consider this very simple pseudo-Java class definition as an analogy:
public class Person {
int age;
Person marriedTo;
}
Using the above query, we would get back the literal that would represent age if the age property is bound. But marriedTo isn't a primitive (i.e. a literal in RDF terms) - it's a reference to another object - in RDF/OWL terminology, that's an object property. But we don't know what sort of objects are being referred to by those properties (predicates). This query will get you back properties with the accompanying types (the classes of which ?o values are members of).
SELECT DISTINCT ?property, ?class
WHERE {
?s a <http://xmlns.com/foaf/0.1/Person>;
?property ?o .
?o a ?class .
FILTER(!isLiteral(?o))
}
That should be enough to orient yourself in a particular dataset. Of course, I'd also recommend that you just pull out some individual resources and inspect them. You can do that using the DESCRIBE query:
DESCRIBE <http://example.org/resource>
There are some SPARQL tools - SNORQL, for instance - that let you do this in a browser. The SNORQL instance I've linked to has a sample query for exploring the possible named graphs, which I haven't covered here.
If you are unfamiliar with SPARQL, honestly, the best resource if you get stuck is the specification. It's a W3C spec but a pretty good one (they built a decent test suite so you can actually see whether implementations have done it properly or not) and if you can get over the complicated language, it is pretty helpful.
I find the following set of exploratory queries useful:
Seeing the classes:
select distinct ?type ?label
where {
?s a ?type .
OPTIONAL { ?type rdfs:label ?label }
}
Seeing the properties:
select distinct ?objprop ?label
where {
?objprop a owl:ObjectProperty .
OPTIONAL { ?objprop rdfs:label ?label }
}
Seeing the data properties:
select distinct ?dataprop ?label
where {
?dataprop a owl:DatatypeProperty .
OPTIONAL { ?dataprop rdfs:label ?label }
}
Seeing which properties are actually used:
select distinct ?p ?label
where {
?s ?p ?o .
OPTIONAL { ?p rdfs:label ?label }
}
Seeing what entities are asserted:
select distinct ?entity ?elabel ?type ?tlabel
where {
?entity a ?type .
OPTIONAL { ?entity rdfs:label ?elabel } .
OPTIONAL { ?type rdfs:label ?tlabel }
}
Seeing the distinct graphs in use:
select distinct ?g where {
graph ?g {
?s ?p ?o
}
}
SELECT DISTINCT * WHERE {
?s ?p ?o
}
LIMIT 10
I often refer to this list of queries from the voiD project. They are mainly of a statistical nature, but not only. It shouldn't be hard to remove the COUNTs from some statements to get the actual values.
Especially with large datasets, it is important to distinguish the pattern from the noise and to understand which structures are used a lot and which are rare. Instead of SELECT DISTINCT, I use aggregation queries to count the major classes, predicates etc. For example, here's how to see the most important predicates in your dataset:
SELECT ?pred (COUNT(*) as ?triples)
WHERE {
?s ?pred ?o .
}
GROUP BY ?pred
ORDER BY DESC(?triples)
LIMIT 100
I usually start by listing the graphs in a repository and their sizes, then look at classes (again with counts) in the graph(s) of interest, then the predicates of the class(es) I am interested in, etc.
Of course these selectors can be combined and restricted if appropriate. To see what predicates are defined for instances of type foaf:Person, and break this down by graph, you could use this:
SELECT ?g ?pred (COUNT(*) as ?triples)
WHERE {
GRAPH ?g {
?s a foaf:Person .
?s ?pred ?o .
}
GROUP BY ?g ?pred
ORDER BY ?g DESC(?triples)
This will list each graph with the predicates in it, in descending order of frequency.

How to search for rdfs:labels in dbpedia which are partial matches to a given term using SPARQL?

I am using this query to search for all labels that contains the word "Medi"
select distinct ?label where
{
?concept rdfs:label ?label
filter contains(?label,"Medi")
filter(langMatches(lang(?label),"en"))
}
However, as soon as I change the term from "Medi" to "Medicare" it doesn't work and times out. How do I get it to work with longer words like Medicare i.e. extract all labels which has the word Medicare in it.
Your query has to iterate over all labels in DBpedia - which is quite a large number - and then apply String containment check. This is indeed expensive.
Even a count query leads to an "estimated timeout error":
select count(?label) where
{
?concept rdfs:label ?label
filter(regex(str(?label),"Medi"))
filter(langMatches(lang(?label),"en"))
}
Two options:
Virtuoso has some fulltext search support:
SELECT DISTINCT ?label WHERE {
?concept rdfs:label ?label .
?label bif:contains "Medicare"
FILTER(langMatches(lang(?label),"en"))
}
Since the public DBpedia endpoint is a shared endpoint, the solution is to load the DBpedia dataset into your own triple store, e.g. Virtuoso. There you can adjust the max. estimated execution timeout parameter.

Listing Properties and Values of an Individual on Dbpedia

How can I list properties with their values for any given DBpedia class? I'm new to this and have looked at several other questions on this but I haven't found exactly what I'm looking for.
What I'm trying to do is providing some relevant additional information to topics of conversation I have got from text mining.
Say for example the topic of conversation in a certain community is iPhones. I would like to use this word to query the DBpedia page for this word, IPhone, to get an output such as:
Type: Smartphone
Operating System: IOS
Manufacturer: Foxconn
EDIT:
Using the query from AKSW I can print the p (property?) and o (object?), although I'm still not getting the output I want. Instead of getting something like:
weight: 133.0
I get
http://dbpedia.org/property/weight:133.0
Is there a way to just get the name of the property instead of the DBpedia link?
My Code
Classes do not "have" properties with values. Instances (resp. resources or individuals) do have a relationship via a property to some value which can be an individual itself or a literal (or some anonymous instance aka blank node). And instances belong to a class. e.g. Berlin belongs to the class City
What you want is to get all outgoing values of a given resource in DBpedia:
SELECT * WHERE { <http://dbpedia.org/resource/IPhone> ?p ?o }
Alternatively, you can use SPARQL DESCRIBE, which return the data in forms of an RDF graph resp. a set of RDF triples:
DESCRIBE <http://dbpedia.org/resource/IPhone>
This might also return incoming information because it's not really specified in the W3C recommendation what has to be returned.
As stated by AKSW properties often link to other classes rather than values. If you want all properties and their values, including other classes the the below gives you the label and filters by language (put the language code you need where have put "en").
SELECT DISTINCT ?label ?o
WHERE {
<http://dbpedia.org/resource/IPhone> ?p ?o.
?p <http://www.w3.org/2000/01/rdf-schema#label> ?label .
FILTER(LANG(?label) = "" || LANGMATCHES(LANG(?label), "en"))
}
If you don't want any properties that link to other classes, then you only want datatype properties so this code could help:
SELECT DISTINCT ?label ?o
WHERE {
<http://dbpedia.org/resource/IPhone> ?p ?o.
?p <http://www.w3.org/2000/01/rdf-schema#label> ?label .
?p a owl:DatatypeProperty .
FILTER(LANG(?label) = "" || LANGMATCHES(LANG(?label), "en"))
}
Obviously this gives you far less information and functionality, but it might just be what you're after?
Edit: In reply to your comment, it is also possible to get the labels for the values, using the same technique:
SELECT DISTINCT ?label ?oLabel
WHERE {
<http://dbpedia.org/resource/IPhone> ?p ?o.
?p <http://www.w3.org/2000/01/rdf-schema#label> ?label .
?o <http://www.w3.org/2000/01/rdf-schema#label> ?oLabel
FILTER(LANG(?label) = "" || LANGMATCHES(LANG(?label), "en"))
}
Note that http://www.w3.org/2000/01/rdf-schema#label is often shortened to rdfs:label by defining prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
So you could also do:
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT DISTINCT ?label ?oLabel
WHERE {
<http://dbpedia.org/resource/IPhone> ?p ?o.
?p rdfs:label ?label .
?o rdfs:label ?oLabel
FILTER(LANG(?label) = "" || LANGMATCHES(LANG(?label), "en"))
}
and get exactly the same result but possibly easier to read.

Sparql to recover the Type of a DBpedia resource

I need a Sparql query to recover the Type of a specific DBpedia resource. Eg.:
pt.DBpedia resource: http://pt.dbpedia.org/resource/Argentina
Expected type: Country (as can be seen at http://pt.dbpedia.org/page/Argentina)
Using pt.DBpedia Sparql Virtuoso Interface (http://pt.dbpedia.org/sparql) I have the query below:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select ?l ?t where {
?l rdfs:label "Argentina"#pt .
?l rdf:type ?t .
}
But it is not recovering anything, just print the variable names. The virtuoso answer.
Actually I do not need to recover the label (?l) too.
Anyone can fix it, or help me to define the correct query?
http in graph name
I'm not sure how you generated your query string, but when I copy and paste your query into the endpoint and run it, I get results, and the resulting URL looks like:
http://pt.dbpedia.org/sparql?default-graph-uri=http%3A%2F%2Fpt.dbpedia.org&sho...
However, the link in your question is:
http://pt.dbpedia.org/sparql?default-graph-uri=pt.dbpedia.org%2F&should-sponge...
If you look carefully, you'll see that the default-graph-uri parameters are different:
yours: pt.dbpedia.org%2F
mine: http%3A%2F%2Fpt.dbpedia.org
I'm not sure how you got a URL like the one you did, but it's not right; the default-graph-uri needs to be http://pt.dbpedia.org, not pt.dbpedia.org/.
The query is fine
When I run the query you've provided at the endpoint you've linked to, I get the results that I'd expect. It's worth noting that the label here is the literal "Argentina"#pt, and that what you've called ?l is the individual, not the label. The individual ?l has the label "Argentina"#pt.
We can simplify your query a bit, using ?i instead of ?l (to suggest individual):
select ?i ?type where {
?i rdfs:label "Argentina"#pt ;
a ?type .
}
When I run this at the Portuguese endpoint, I get these results:
If you don't want the individual in the results, you don't have to select it:
select ?type where {
?i rdfs:label "Argentina"#pt ;
a ?type .
}
or even:
select ?type where {
[ rdfs:label "Argentina"#pt ; a ?type ]
}
If you know the identifier of the resource, and don't need to retrieve it by using its label, you can even just do:
select ?type where {
dbpedia-pt:Argentina a ?type
}
type
==========================================
http://www.w3.org/2002/07/owl#Thing
http://www.opengis.net/gml/_Feature
http://dbpedia.org/ontology/Place
http://dbpedia.org/ontology/PopulatedPlace
http://dbpedia.org/ontology/Country
http://schema.org/Place
http://schema.org/Country

How to match exact string literals in SPARQL?

I have this query. It matches anything which has "South" in its name. But I only want the one whose foaf:name is exactly "South".
SELECT Distinct ?TypeLabel
WHERE
{
?a foaf:name "South" .
?a rdf:type ?Type .
?Type rdfs:label ?TypeLabel .
}
a bit late but anyway... I think this is what your looking for:
SELECT Distinct ?TypeLabel Where {
?a foaf:name ?name .
?a rdf:type ?Type .
?Type rdfs:label ?TypeLabel .
FILTER (?name="South"^^xsd:string)
}
you can use FILTER with the xsd types in order to restrict the result.
hope this helps...
cheers!
(Breaking out of comments for this)
Data issues
The issue is the data, not your query. If use the following query:
SELECT DISTINCT ?a
WHERE {
?a foaf:name "Imran Khan" .
}
You find (as you say) "Imran Khan Niazy".
But looking at the dbpedia entry for Imran Khan, you'll see both:
foaf:name "Imran Khan Niazy"
foaf:name "Imran Khan"
This is because RDF allows repeated use of properties.
Cause
"South" had the same issue (album, artist, and oddly 'South Luton'). These are cases where there are both familiar names ("Imran Khan", "South"), and more precise names ("Imran Khan Niazy", "South (album)") for the purposes of correctness or disambiguation.
Resolution
If you want a more precise match try adding a type (e.g. http://dbpedia.org/ontology/MusicalWork for the album).
Beware
Be aware that DBpedia derives from Wikipedia, and the extraction process isn't perfect. This is an area alive with wonky data, so don't assume your query has gone wrong.
That query should match exactly the literal South and not literals merely containing South as a substring. For partial matches you'd go to FILTER with e.g. REGEX(). Your query engine is broken in this sense - which query engine you are working with?