Wikidata:Wikibase GraphQL
|
Wikidata For Developers |
Overview
[edit]Wikibase GraphQL is a GraphQL API for Wikidata. It is a flexible alternative to a few simple Wikidata Query Service (WDQS) use cases, with a strong focus on developer experience, flexibility, and efficient data retrieval.
For development progress and upcoming features, see the Wikibase GraphQL Phabricator workboard
Background
[edit]The Wikibase GraphQL API was developed following an investigation into alternative ways of accessing Wikidata and Wikibase content that reduce load on the Wikidata Query Service (WDQS), improve the developer experience for common read use cases and allow more flexible data retrieval in a single request.
As part of this investigation, a Wikibase GraphQL prototype was built to explore what is technically possible and whether GraphQL would be a good fit for Wikibase data, with promising results and supportive feedback.
The GraphQL API has the following functionality for now:
- Fetching labels of linked entities
- Retrieving multiple Items at once
- Searching items by statement property and value
- Look up item by Sitelink
- Look up item by external identifier
Why should I use the Wikibase GraphQL API?
[edit]- One-stop shop: Multiple data needs can be fulfilled from a single API endpoint, such as searching for entities, retrieving statements, and fetching labels or descriptions of linked entities.
- Flexible and expressive: Clients can decide which fields they want, reducing over-fetching and under-fetching of data.
- Excellent tooling: GraphQL comes with mature tooling such as interactive documentation via GraphiQL, strong client libraries (e.g. Apollo Client), and built-in schema introspection.
- Well-suited for linked data: Traversing direct relationships and requesting labels of linked entities is a core strength of GraphQL.
How to use the GraphQL API
[edit]Web-based interactive clients
[edit]The easiest way to explore the Wikibase GraphQL API is from your web browser via interactive GraphQL clients, which provide schema documentation, auto-completion, and immediate feedback.
- GraphiQL: An interactive GraphiQL client is available on doc.wikimedia.org.
- Apollo Sandbox Explorer: A web-based GraphQL explorer provided by Apollo.
Other clients
[edit]The GraphQL API can also be accessed using generic HTTP or GraphQL clients, including Altair, Bruno. Insomnia or Postman. These tools are useful for testing, scripting, and integration into non-JavaScript environments.
You can access the API on Wikidata using the base URL: .
https://www.wikidata.org/w/api.php?action=wbgraphql&format=json
Refer to the User-Agent policy and global rate limits when using the API.
GraphQL Schema
[edit]The GraphQL type system describes what data can be queried from the API. The collection of those capabilities is referred to as the serviceâs schema and can be expressed using the Schema Definition Language (SDL). You can find the Wikibase GraphQL schema file in the wikibase code repository or generate it from the GraphQL endpoint using tools such as get-graphql-schema.
Code example
[edit]A couple of things to keep in mind: when making requests
- You always need to set a User-Agent.
- You should send your query and request as JSON.
- Send requests as POST.
- When making requests from a web browser, you might need to set
origin=*in the endpoint to do CORS calls.
requests library.import requests
ENDPOINT = "https://www.wikidata.org/w/api.php?action=wbgraphql&format=json"
QUERY = """
query example {
item(id: "Q64") {
label(languageCode: "en")
}
}
"""
req = requests.post(
url = ENDPOINT,
json = {
"format" : "json",
"query" : QUERY
},
headers = {
# Change this to your own app and details!
"User-Agent" : "User-Agent: CoolBot/0.0 (https://example.org/coolbot/; coolbot@example.org) generic-library/0.0"
}
)
print(req.json())
Functionality
[edit]Fetching labels of linked entities
[edit]Request labels and/or descriptions of:
- statement properties,
- entities used as statement values.
This allows clients to retrieve human-readable data without issuing many follow-up requests.
Example
[edit]Fetch the English label for Item Q64 (Berlin) and all its statement values for the properties P31 instance of (ItemValue), P18 image (Commons Media File) and P571 inception (Point in time).
| Query | Response |
|---|---|
query exampleQuery_item {
item(id: "Q64") {
label(languageCode: "en")
instance_of: statements(propertyId: "P31") {
value {
... on ItemValue {
id
label(languageCode: "en")
}
}
}
image: statements(propertyId: "P18") {
value {
... on CommonsMediaValue { content }
}
}
inception: statements(propertyId: "P571") {
value {
... on TimeValue { time }
}
}
}
}
|
{
"data": {
"item": {
"label": "Berlin",
"instance_of": [
{
"value": {
"id": "Q1901835",
"label": "seat of government"
}
},
{
"value": {
"id": "Q200250",
"label": "metropolis"
}
},
...
],
"image": [
{
"value": {
"content": "Cityscape Berlin.jpg"
}
}
],
"inception": [
{
"value": {
"time": "+1244-00-00T00:00:00Z"
}
}
]
}
}
}
|
This example shows the use of aliases to query three different statement fields (instance_of, image and inception) and the use of inline fragments with the spread operator (... on <ValueType>) to access data on the various underlying statement value types.
Retrieving multiple Items at once
[edit]Fetch up to 50 Items in a single request. This is useful for applications that already know a set of Item IDs and want to fetch their data efficiently.
Example
[edit]Fetch Items Q64 (Berlin), Q84 (London) and Q90 (Paris) with their English labels, labels with language fallback, statement values for the Property P2046 area (Quantity) and their ranks.
| Query | Response |
|---|---|
query itemsById {
itemsById(ids: ["Q64", "Q84", "Q90"]) {
label(languageCode: "en")
labelWithLanguageFallback(languageCode: "de") {
languageCode
value
}
area: statements(propertyId: "P2046") {
value {
... on QuantityValue { amount }
}
rank
}
}
}
|
{
"data": {
"itemsById": [
{
"label": "Berlin",
"labelWithLanguageFallback": {
"languageCode": "de",
"value": "Berlin"
},
"area": [
{
"value": {
"amount": "+891.69"
},
"rank": "NORMAL"
},
{
"value": {
"amount": "+891.12"
},
"rank": "PREFERRED"
}
]
},
{
"label": "London",
"labelWithLanguageFallback": {
"languageCode": "de",
"value": "London"
},
"area": [
{
"value": {
"amount": "+1572"
},
"rank": "NORMAL"
}
]
},
{
"label": "Paris",
"labelWithLanguageFallback": {
"languageCode": "de",
"value": "Paris"
},
"area": [
{
"value": {
"amount": "+105.4"
},
"rank": "PREFERRED"
}
]
}
]
}
}
|
This example shows the use of labelWithLanguageFallback field, which returns the label in the requested language if it exists, otherwise using the language fallback chain to find a label in another language. The response includes both the label value and the language code of the returned label, so clients can tell whether the requested language or a fallback language was used.
Searching items by statement property and value
[edit]Find Items that match specific statement propertyâvalue pairs, such as:
- âinstance of: catâ (Q146)
- âoccupation: art modelâ (Q1630100)
- combinations of multiple conditions using logical AND and OR.
searchItems limitations
[edit]For now, searchItems only works with string-like values and item values in its property-value pair filters. It is powered by WikibaseCirrusSearch and thus also inherits its constraints:
- For performance reasons, certain properties are intentionally not indexed even if their data type is otherwise supported. On Wikidata, this currently includes P1433 (published in) and P2860 (cites work). Searching for these properties will return no results.
- Only indexed items are returned. Items not yet processed by CirrusSearch's indexing pipeline will not appear in results even if they match the query.
Pagination
[edit]The searchItems field supports cursor-based pagination, which allows fetching large result sets one page at a time.
Use the first parameter to set the page size (with a default of 10 and a maximum of 50) and the after parameter to continue from where the previous page left off. The cursor to pass as after is found in the pageInfo.endCursor field of the previous response.
Example
[edit]Find the first two Items that have property P21 (sex or gender) with value Q6581072 (female), and property P101 (field of work) with values Q82594 (computer scientist) or Q179310 (computing). Show their IDs, English labels, and English Wikipedia sitelink title and URL in the response. Additionally, show page information with start and end cursors.
| Query | Response |
|---|---|
query searchItems {
searchItems(
query: {
and: [
{ property: "P21", value: "Q6581072" },
{ or: [
{ property: "P101", value: "Q82594" },
{ property: "P101", value: "Q179310" }
] }
]
}
first: 2
) {
edges {
node {
id
label(languageCode: "en")
sitelink(siteId: "enwiki") {
title
url
}
}
}
pageInfo {
startCursor
hasPreviousPage
hasNextPage
endCursor
}
}
}
|
{
"data": {
"searchItems": {
"edges": [
{
"node": {
"id": "Q11749",
"label": "Lydia E. Kavraki",
"sitelink": {
"title": "Lydia Kavraki",
"url": "https://en.wikipedia.org/wiki/Lydia_Kavraki"
}
}
},
{
"node": {
"id": "Q7259",
"label": "Ada Lovelace",
"sitelink": {
"title": "Ada Lovelace",
"url": "https://en.wikipedia.org/wiki/Ada_Lovelace"
}
}
}
],
"pageInfo": {
"startCursor": "MDAwMDAwMDAwMQ==",
"hasPreviousPage": false,
"hasNextPage": true,
"endCursor": "MDAwMDAwMDAwMg=="
}
}
}
}
|
Note:
or:can be used at the top level (instead ofand:) or nested within anand:clause as shown above. The reverse is not possible âand:cannot be used inside anor:clause. This means only two levels of nesting are supported, and complex boolean expressions are not possible.- you can paginate through a maximum of 10,000 results in total.
- all item fields can be queried.
Look up item by Sitelink
[edit]The itemBySitelink field returns an Item if the sitelink uniquely identifies one Item. If no Item exists for the given site ID and title, it returns null.
Example
[edit]Look up the Item for the French Wikipedia page Jeanne d'Arc with its English label, English description, and English Wikipedia sitelink title and URL.
| Query | Response |
|---|---|
query itemByFrenchSitelink {
itemBySitelink(
siteId: "frwiki"
title: "Jeanne d'Arc"
) {
id
label(languageCode: "en")
description(languageCode: "en")
sitelink(siteId: "enwiki") {
title
url
}
}
}
|
{
"data": {
"itemBySitelink": {
"id": "Q7226",
"label": "Joan of Arc",
"description": "French folk heroine (1412â1431), military leader who crowned Charles VII and Roman Catholic saint, canonized 500 years after her death",
"sitelink": {
"title": "Joan of Arc",
"url": "https://en.wikipedia.org/wiki/Joan_of_Arc"
}
}
}
}
|
Look up item by external identifier
[edit]The itemByExternalId field returns an Item if the external identifier uniquely identifies one Item. If multiple Items use the same external identifier, it returns ExternalIdNonUnique with the matching Item IDs.
Example
[edit]Look up the Item for an external identifier. In this example, property P345 (IMDb ID).
| Query | Response |
|---|---|
query itemByExternalId {
itemByExternalId(property: "P345",
externalId: "tt0118715") {
... on Item {
id
label(languageCode: "en")
description(languageCode: "en")
}
... on ExternalIdNonUnique {
items
}
}
}
|
{
"data": {
"itemByExternalId": {
"id": "Q337078",
"label": "The Big Lebowski",
"description": "1998 film by Joel Coen, Ethan Coen"
}
}
}
|
If the external identifier is not unique, the same query can return matching Item IDs instead:
| Query | Response |
|---|---|
query itemByExternalIdNonUnique {
itemByExternalId(property: "P212", externalId: "978-3-440-09723-6") {
... on Item {
id
label(languageCode: "en")
description(languageCode: "en")
}
... on ExternalIdNonUnique {
items
}
}
}
|
{
"data": {
"itemByExternalId": {
"items": [
"Q106075503",
"Q105617592",
"Q135645865"
]
}
}
}
|
Feedback and development
[edit]The Wikibase GraphQL API is under active development, and community feedback is highly encouraged. Options to get in touch:
- Answer the embedded, single question survey at the top of the page.
- Leave a comment on this pageâs discussion page, or +1 someone elseâs comment.
- Create a Phabricator ticket with the tag: Wikibase GraphQL