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

1.8k Views Asked by At

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

There are 1 best solutions below

3
On

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