In this section
If you’re new to GraphQL, check out the many resources to learn GraphQL. For example, Introduction to GraphQL. To get you started, here are some common GraphQL query-related concepts you should understand.
The GraphQL schema tells you what queries are allowed. The schema defines the objects, object types, and attributes that you can get from the Tableau Metadata API.
The building block of a query is the object. Objects are a collection of data assets accessible from the Metadata API. Objects have object types and attributes.
GraphQL operations come in the form of queries. Queries are also objects, specifically root objects in GraphQL. However, queries are special objects because they define the entry point of every GraphQL query.
For example, suppose you have the following GraphQL query:
query {
hello
}
The operation above begins with the required query
root object. The object being requested is hello
. The result of the query is:
"data": {
"hello": "world"
},
As you can see, GraphQL returns data in a similar shape as the query itself.
After identifying the data that you’re interested in, you can write a query to access the information.
To answer what types of databases and tables are used on your site, you might use the following query:
query getDatabasesOnMySite{
databases {
id
name
}
}
query getTablesTablesOnMySite{
tables {
id
name
}
}
Here, databases
and tables
are objects and id
and name
are attributes in the Metadata API that you can query.
To find a specific table, such as the Orders table, you can pass a filter parameter with a value of “Orders” through the tables
object. Your query might look like the following:
query ShowMeOneTableCalledOrders{
tables (filter: {name: "Orders"}){
name
columns {
name
}
}
}
Here, tables
is the object and name
and columns
are attributes in the Metadata API that you can query. The filter parameter that you pass through the table
object uses the format (filter: {name: "<name-of-the-table>"})
.
To find a specific table in a workbook using a dynamic value instead of a static value in the filter parameter, you can use a query variable. A query variable is value that you can define outside of the query so that it can be changed dynamically. This query variable is a second object that’s passed through the same query.
The query variable uses the following formats depending on where the query variable is being used:
variableName: <value>
{name: $variableName}
For example, suppose you want to use a query variable to find the Sample_Superstore workbook. You might use the following query, where the query variable is “$workbookname” and the value for the variable in this example is “Sample_Superstore”.
query ShowMeAnyTable($workbookName: String, $sheetName: String){
workbooks(filter: {name: $workbookName}){
name
embeddedDataSources {
fields {
name
...on CalculatedField {
formula
}
}
}
sheets(filter: {name: $sheetName}){
name
worksheetFields {
name
formula
}
}
}
}
A filter sorts through and retrieves only the data that meets a set of specified criteria.
For example, suppose you’re looking for a published data source named “Orders.” You might use the following query to find information about the published data source:
query FilteredQuery {
publishedDatasources(filter: {name: "Orders"}) {
name
hasExtracts
upstreamTables
}
}
Here, the filter parameter that you pass through the publishedDataSources
object uses the format (filter: {name: "<name-of-the-data-source>"})
.
Suppose you’re looking for multiple published data sources, “Orders” and “Education.” You might use the following query to find information about these published data sources:
query FilteredWithinQuery {
publishedDatasources(filter: {nameWithin: ["Orders", "Education"]}) {
name
hasExtracts
upstreamTables
}
}
To filter for multiple published data sources, the filter parameter that you pass through the publishedDataSources
object uses the format (filter: {namewithin: ["<name-of-the-data-source1>", "<name-of-the-data-source2>"]})
.
Pagination enables you to traverse through relationships among the data that you’re querying. The Metadata API defines pagination objects as those that have “Connection” appended to it.
There are two common methods for pagination that these objects can support: offset and cursors. The maximum page size using either method is 1,000 items.
Using the offset method, you can specify the number of items you want and where to start counting the items you want retrieved. This method allows for larger queries. However, it also might affect performance of the query as the query gets larger.
For example, suppose you want to retrieve data about published data sources. In the publishedDataSourcesConnections
object parameter you can specify the number of items you want using “first” and where to start counting the items you want retrieved using “offset”.
The following query gives you the first ten items.
query PaginatedQueryOffsetPage1 {
publishedDatasourcesConnection(first: 10, offset: 0) {
nodes {
name
}
}
}
Here, the pagination format you can use for offset is (first: <value>, offset: <value>)
.
The following query gives you the next ten items, for a total of 20 items.
query PaginatedQueryOffsetPage2 {
publishedDatasourcesConnection(first: 10, offset: 10) {
nodes {
name
}
}
}
Using cursors, you can retrieve data by specifying the page size and then using a “cursor” to keep track of where the next set of data should be retrieved from. This method is faster than the offset method when you need return results for large lists.
For example, suppose you want to retrieve data about published data sources. In the publishedDataSourcesConnection object parameter, you can specify the number of items you want using “first”.
Then, instead of counting pages using “offset” like in the offset method, you pass in “after” when using the cursor method, which is a value that is returned by the pageInfo attribute in the publishedDataSourcesConnection object.
query PaginatedQueryCursorPage1 {
publishedDatasourcesConnection(first: 10, orderBy: {field: NAME, direction: ASC}) {
nodes {
name
}
pageInfo {
hasNextPage
endCursor
}
}
}
Notes:
When you include “after” in the parameter, the value of the “endCursor” is passed into a subsequent query.
query PaginatedQueryCursorPage2 {
publishedDatasourcesConnection(first: 10, after: null, orderBy: {field: NAME, direction: ASC}) {
nodes {
name
}
pageInfo {
hasNextPage
endCursor
}
}
}
When querying fields, you can include a description inheritance object, descriptionInherited
, in your query to return information about the closest upstream object where the description is inherited from. Including this description inheritance object in your query can be useful for providing supplemental description information associated with upstream objects.
The following query returns description attribute information for fields in all data sources that are associated with the specified table.
query whereIsThisDescriptionComingFrom {
databaseTables(filter: {id: "57a8c84f-0671-4df5-964b-774fc68968b1"}) {
downstreamDatasources {
fields {
description
descriptionInherited {
value
asset {
id
__typename
}
}
}
}
}
}
There are two permission modes available in the Metadata API:
If you do not specify a permissions mode in a query, the default permission mode, obfuscate, is applied. Obfuscate returns all results, but will hide any sensitive attributes on external assets that you do not have permissions to see. For more information, see Access Metadata about Related Asset section of the How Permissions Work topic.
You can explicitly specify the obfuscate permissions mode by passing the permissions mode parameter through the object using the format (permissionMode: OBFUSCATE_RESULTS)
like in the example below.
query ObfuscatePermissionsQuery {
databases(permissionMode: OBFUSCATE_RESULTS) {
tables{
downstreamDatasources{
name
}
}
}
}
In the example query above, although you might not have permissions to all the databases, the obfuscate permissions mode returns all the related data sources that you have permissions to see.
If you specify the filter permissions mode, only the results whose attributes of external assets you have permissions to see are returned.
You can specify the filter permissions mode by passing the permissions mode parameter through the object using the format (permissionMode: FILTER_RESULTS)
like in the example below.
query FilteredPermissionsQuery {
databases(permissionMode: FILTER_RESULTS) {
tables{
downstreamDatasources{
name
}
}
}
}
In the example query above, because you might not have permissions to all the database, the filter permissions mode returns only the data sources that are related to the databases and tables that you have permissions to see. This means, a query like this might omit data sources that you might have permissions to see.
You can use linked flow objects in a query to return information about which flows are directly upstream or downstream of one another.
The following query returns all the downstream flow objects that have a relationship to Flow1.
query flows {
flows (filter: {name: "Flow1"}){
name
downstreamLinkedFlows{
asset{
name
id
}
toEdges
fromEdges
}
}
}
For more information about linked flow objects, see Working with linked flow objects.