How to get all properties for only a specific category in Wikidata? - sparql

Is there an RDF data/other format that allow me to get all the properties that can exist in a category e.g. Person, then I should be returned properties like sex, date of birth.
How to query this information at https://query.wikidata.org/ ?
What I want is this https://www.wikidata.org/wiki/Wikidata:List_of_properties/Summary_table
But is there a better format for this? I want to access programmatically.
UPDATE
This query is too heavy, causes timeout.
SELECT ?p ?attName WHERE {
?q wdt:P31 wd:Q5.
?q ?p ?statement.
?realAtt wikibase:claim ?p.
?realAtt rdfs:label ?attName.
FILTER(((LANG(?attName)) = "en") || ((LANG(?attName)) = ""))
}
GROUP BY ?p ?attName
I must specify the entity, e.g. to Barrack Obama then it works, but this does not give me the all possible properties.
SELECT ?p ?attName WHERE {
BIND(wd:Q76 AS ?q)
?q wdt:P31 wd:Q5.
?q ?p ?statement.
?realAtt wikibase:claim ?p.
?realAtt rdfs:label ?attName.
FILTER(((LANG(?attName)) = "en") || ((LANG(?attName)) = ""))
}
GROUP BY ?p ?attName

1
The page you have linked to is created by a bot. Contact the BetaBot operator, if you need to know how the bot works.
2
Perhaps the bot relies on the wd:P1963 property:
SELECT ?property ?propertyLabel {
VALUES (?class) {(wd:Q5)}
?class wdt:P1963 ?property
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
} ORDER BY ASC(xsd:integer(strafter(str(?property), concat(str(wd:), "P"))))
The above query returns 49 results.
3
I'd suggest you rely on type constraints from property pages:
SELECT ?property ?propertyLabel {
VALUES (?class) {(wd:Q5)}
?property a wikibase:Property .
?property p:P2302 [ ps:P2302 wd:Q21503250 ;
pq:P2309 wd:Q21503252 ;
pq:P2308 ?class ] .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
} ORDER BY ASC(xsd:integer(strafter(str(?property), concat(str(wd:), "P"))))
The above query returns 700 results.
4
The first query from your question works fine for relatively small classes, e. g. wd:Q6256 ('country'). On the public endpoint, it is not possible to make the query work for large classes.
However, you could split the query into small parts. In Python:
from wdqs import Client
from time import sleep
client = Client()
result = client.query("SELECT (count(?p) AS ?c) {?p a wikibase:Property}")
count = int(result[0]["c"])
offset = 0
limit = 50
possible = []
while offset <= count:
props = client.query("""
SELECT ?property WHERE {
hint:Query hint:optimizer "None" .
{
SELECT ?property {
?property a wikibase:Property .
} ORDER BY ?property OFFSET %s LIMIT %s
}
?property wikibase:directClaim ?wdt.
FILTER EXISTS {
?human ?wdt [] ; wdt:P31 wd:Q5 .
hint:Group hint:maxParallel 501 .
}
hint:Query hint:filterExists "SubQueryLimitOne" .
# SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
}
""" % (offset, limit))
for prop in props:
possible.append(prop['property'])
offset += limit
print (len(possible), min(offset, count))
sleep(0.25)
The last line of the output is:
2156 5154

Related

SPARQL limit result of only one variable

I am trying to query wikidata to retrieve artworks, their material characteristics and the artistic movement they are associated with. Each resulting record can have a number of movements/materials associated with (as an artwork can be classified as belonging to two movements at the same time, or with different materials).
I would like to retrieve for each artwork only one of the movement/material associated with, as not to have duplicate lines in the results to manually remove afterwards.
How can I achieve such result using only SPARQL?
Here's my current query:
SELECT DISTINCT ?artwork ?image ?time ?creatorLabel ?movementLabel ?materialLabel WHERE {
?artwork wdt:P31 wd:Q3305213 ;
wdt:P571 ?time ;
wdt:P18 ?image .
OPTIONAL {
?artwork wdt:P170 ?creator
}
OPTIONAL {
?artwork wdt:P135 ?movement.
}
OPTIONAL {
?artwork wdt:P186 ?material.
}
FILTER(?time > "1870-01-01T00:00:00"^^xsd:dateTime)
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". } # Helps get the label in your language, if not, then en language
}
LIMIT 100
I tried to use COUNT and HAVING (HAVING (COUNT(?material) < 2)) to limit the result, but with such method I get a timeout. Is there any other way?
You can use SAMPLE, which picks an arbitrary value:
SELECT DISTINCT ?artwork ?image ?time ?creatorLabel (SAMPLE(?movementLabel) AS ?movementLabel_sample) (SAMPLE(?materialLabel) AS ?materialLabel_sample)
WHERE {
{
SELECT ?artwork ?image ?time ?creatorLabel ?movementLabel ?materialLabel
WHERE {
VALUES ?artwork { wd:Q728373 wd:Q720602 } # remove this line to query all artworks
?artwork wdt:P31 wd:Q3305213 ;
wdt:P571 ?time ;
wdt:P18 ?image .
OPTIONAL { ?artwork wdt:P170 ?creator . }
OPTIONAL { ?artwork wdt:P135 ?movement . }
OPTIONAL { ?artwork wdt:P186 ?material. }
FILTER(?time > "1870-01-01T00:00:00"^^xsd:dateTime)
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". } # Helps get the label in your language, if not, then en language
}
}
}
GROUP BY ?artwork ?image ?time ?creatorLabel
LIMIT 100
But if your only concern is
not to have duplicate lines in the results to manually remove afterwards
you could use GROUP_CONCAT to get one line per artwork, with multiple values per cell:
SELECT DISTINCT ?artwork ?image ?time ?creatorLabel (GROUP_CONCAT(DISTINCT ?movementLabel; separator=", ") AS ?movementLabels) (GROUP_CONCAT(DISTINCT ?materialLabel; separator=", ") AS ?materialLabels)
WHERE {
{
SELECT ?artwork ?image ?time ?creatorLabel ?movementLabel ?materialLabel
WHERE {
VALUES ?artwork { wd:Q728373 wd:Q720602 } # remove this line to query all artworks
?artwork wdt:P31 wd:Q3305213 ;
wdt:P571 ?time ;
wdt:P18 ?image .
OPTIONAL { ?artwork wdt:P170 ?creator . }
OPTIONAL { ?artwork wdt:P135 ?movement . }
OPTIONAL { ?artwork wdt:P186 ?material. }
FILTER(?time > "1870-01-01T00:00:00"^^xsd:dateTime)
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } # Helps get the label in your language, if not, then en language
}
}
}
GROUP BY ?artwork ?image ?time ?creatorLabel
LIMIT 100
(If there can be multiple images, times, or creators, you could do the same for these properties, too.)

Path matching inside a VALUES clause

I'm trying to perform path matching inside a VALUES clause in sparql in order to match all instances and subclasses of both battles and sieges in wikidata. The following request repeatedly times out.
SELECT DISTINCT ?battle ?battleLabel WHERE {
{
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
VALUES ?type {wd:Q178561 wd:Q188055} ?battle (wdt:P31/wdt:P279*) ?type .
?battle rdfs:label ?queryByTitle.
FILTER(REGEX(?queryByTitle, "saratoga", "i"))
}
}
It seems that VALUES, esp. in conjunction with /, confuses the Blazegraph's query optimizer in that case.
Use UNION instead of VALUES:
SELECT DISTINCT ?battle ?battleLabel WHERE {
{ ?battle wdt:P31/wdt:P279* wd:Q178561 }
UNION
{ ?battle wdt:P31/wdt:P279* wd:Q188055 }
?battle rdfs:label ?queryByTitle.
FILTER(REGEX(?queryByTitle, "saratoga", "i"))
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en" }
}
Alternatively, disable the optimizer and specify explicit order:
SELECT DISTINCT ?battle ?battleLabel WHERE {
hint:Query hint:optimizer "None" .
VALUES ?type {wd:Q178561 wd:Q188055}
?subtype wdt:P279* ?type .
?battle wdt:P31 ?subtype .
?battle rdfs:label ?queryByTitle.
FILTER(REGEX(?queryByTitle, "saratoga", "i"))
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en" }
}

Get alias values from Wikidata for a given property?

For a given property like 'occupation (P106)', I want to retrieve all its aliases like: profession, job, work, career, employment, craft. All of this is present on the properties wikidata page, under 'Also known as'. How can I go about retrieving this using SPARQL?
I tried using the following query.
SELECT ?predicate ?object WHERE {
wdt:P106 wdt:P1449 ?predicate . //Nickname
wdt:P106 wdt:P734 ?predicate . //Family Name
wdt:P106 wdt:P735 ?predicate . //Given Name
wdt:P106 skos:altLabel ?predicate .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
SELECT ?altLabel
{
VALUES (?wd) {(wd:P106)}
?wd skos:altLabel ?altLabel .
FILTER (lang(?altLabel) = "en")
}
or
SELECT ?altLabel
{
VALUES (?wdt) {(wdt:P106)}
?wd wikibase:directClaim ?wdt .
?wd skos:altLabel ?altLabel .
FILTER (lang(?altLabel) = "en")
}
These paragraphs provide some explanation:
Truthy statements
Properties
Predicates
Update
You still could use the label service:
SELECT ?wdAltLabel
{
VALUES (?wdt) {(wdt:P106)}
?wd wikibase:directClaim ?wdt .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}

Wikidata SPARQL query cast & crew

My objective is to create a sparql query that retrieves a list of cast and crew and it's wikidata type ("director", "screenwriter", "cast member", ...)
So far I have this:
SELECT ?titleLabel ?castLabel ?property ?propertyLabel
WHERE {
?title wdt:P345 "tt0848228".
?title wdt:P57 ?cast.
?property wikibase:propertyType ?propertyType.
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
The output I want to achive is a table with rows like:
"The Avengers", "Joss Whedon", "wd:P57", "director"
...
I came up with this query:
SELECT ?titleLabel ?castLabel ?property ?propLabel
WHERE {
?title wdt:P345 "tt0848228".
# take all claims on this movie
?title ?property ?cast .
# that involve a human
?cast wdt:P31 wd:Q5 .
# get the property label
# see https://www.wikidata.org/wiki/Wikidata:SPARQL_query_service/queries#Adding_labels_for_properties
hint:Query hint:optimizer "None" .
?prop wikibase:directClaim ?property .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}

How to retrieve aliases from wikidata

I'm trying to retrieve some information from Wikidata and I have found interesting to collect the aliases of the voices. For examples Francesco Totti is also known as il Capitano or er Pupone :
I'm trying to retrieve all the serie a's football players with this sparql query:
SELECT ?subject ?nomeLabel ?cognomeLabel ?subjectLabel WHERE {
?subject wdt:P31 wd:Q5.
?subject p:P54 ?team .
?team ps:P54 wd:""" + team_code +""" .
FILTER NOT EXISTS { ?team pq:P582 ?end
}
OPTIONAL{
?subject wdt:P735 ?nome .
?subject wdt:P734 ?cognome .
}
SERVICE wikibase:label { bd:serviceParam wikibase:language "it". }
}
ORDER BY (?cognomeLabel)
How I can modify my query to take also the aliases?
Thanks
I have attempted a query with various labels. Here just for Roma:
SELECT distinct ?subject ?subjectLabel ?nomeLabel ?cognomeLabel ?nickname ?alternative ?subjectAltLabel WHERE {
?subject wdt:P31 wd:Q5.
?subject p:P54 ?team .
?team ps:P54 wd:Q2739 .
FILTER NOT EXISTS { ?team pq:P582 ?end . }
OPTIONAL { ?subject wdt:P735 ?nome . }
OPTIONAL { ?subject wdt:P734 ?cognome . }
OPTIONAL { ?subject wdt:P1449 ?nickname . }
OPTIONAL { ?subject skos:altLabel ?alternative . }
SERVICE wikibase:label { bd:serviceParam wikibase:language "it,en,fr". }
}
ORDER BY (?cognomeLabel)
I believe the P1449 property should be the most appropriate property to store an alias/nickname, but it does not seem to be used that much for football players. I just added "il Capitano" to Francesco Totti. Beyond that one there does not seem to be other nicknames for Roma players.
The "Also known as" label (in the right column) is not necessarily the nickname, but may be a spelling variation.
Something more generic if someone is interested in all properties that will return only the english also known as:
SELECT ?property ?propertyLabel ?propertyDescription (GROUP_CONCAT(DISTINCT(?altLabel); separator = ", ") AS ?altLabel_list) WHERE {
?property a wikibase:Property .
OPTIONAL { ?property skos:altLabel ?altLabel . FILTER (lang(?altLabel) = "en") }
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" .}
}
GROUP BY ?property ?propertyLabel ?propertyDescription
LIMIT 5000
Another more simple example for male actors with itemAltLabel :
#Male Actors
SELECT ?item ?itemLabel ?itemAltLabel
WHERE
{
?item wdt:P21 wd:Q6581097.
?item wdt:P106 wd:Q33999.
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}