Edit

Share via


Field selection (Projection) in GraphQL

In GraphQL, the fields you request define exactly what Data API builder (DAB) returns, no more, no less. DAB compiles these selections into parameterized SQL, including only the mapped (exposed) columns you asked for and any extra columns it must fetch internally. These may include columns required for relationships (foreign keys), primary keys, or stable ordering used in pagination and cursor construction.

Note

GraphQL has no wildcard like SELECT *. Clients must specify each field explicitly.

Go to the REST version of this document.

Basic selection

Querying a few mapped fields.

GraphQL query

query {
  books {
    items {
      id
      title
      price
    }
  }
}

Conceptual SQL

SELECT
  id,
  sku_title AS title,
  sku_price AS price
FROM dbo.books;

Sample response

{
  "data": {
    "books": {
      "items": [
        {
          "id": 1,
          "title": "Dune",
          "price": 20
        }
      ]
    }
  }
}

Field aliases

Aliases rename fields in the response, not in the database. The SQL layer doesn't alias to GraphQL field names; aliasing happens after data retrieval.

query {
  books {
    items {
      id
      bookTitle: title
      cost: price
    }
  }
}

Conceptual SQL

SELECT
  id,
  sku_title AS title,
  sku_price AS price
FROM dbo.books;

Sample response

With aliases:

{
  "data": {
    "books": {
      "items": [
        {
          "id": 2,
          "bookTitle": "Foundation",
          "cost": 18
        }
      ]
    }
  }
}

Nested selection

Relationships defined in the configuration allow nested queries. The conceptual SQL below shows a single join. In practice, DAB may execute one or more parameterized queries (for example, a parent query plus a batched child fetch) rather than a single flattened join.

GraphQL query

query {
  books {
    items {
      id
      title
      category {
        id
        name
      }
    }
  }
}

Conceptual SQL

SELECT
  b.id,
  b.sku_title AS title,
  c.id AS category_id,
  c.name AS category_name
FROM dbo.books AS b
JOIN dbo.categories AS c
  ON b.category_id = c.id;

Sample response

{
  "data": {
    "books": {
      "items": [
        {
          "id": 1,
          "title": "Dune",
          "category": {
            "id": 10,
            "name": "Sci-Fi"
          }
        },
        {
          "id": 2,
          "title": "Foundation",
          "category": {
            "id": 10,
            "name": "Sci-Fi"
          }
        }
      ]
    }
  }
}

One-to-many selection

You can also traverse the inverse relationship. Again, SQL is conceptual; actual execution may deduplicate parent rows and materialize child collections separately.

GraphQL query

query {
  categories {
    items {
      id
      name
      books {
        items {
          id
          title
        }
      }
    }
  }
}

Conceptual SQL

SELECT
  c.id,
  c.name,
  b.id AS book_id,
  b.sku_title AS title
FROM dbo.categories AS c
JOIN dbo.books AS b
  ON c.id = b.category_id;

Sample response

{
  "data": {
    "categories": {
      "items": [
        {
          "id": 10,
          "name": "Sci-Fi",
          "books": {
            "items": [
              { "id": 1, "title": "Dune" },
              { "id": 2, "title": "Foundation" }
            ]
          }
        }
      ]
    }
  }
}

Example configuration

{
  "runtime": {
    "pagination": {
      "default-page-size": 100,
      "max-page-size": 100000
    }
  },
  "entities": {
    "Book": {
      "source": {
        "type": "table",
        "object": "dbo.books"
      },
      "mappings": {
        "sku_title": "title",
        "sku_price": "price"
      },
      "relationships": {
        "book_category": {
          "cardinality": "one",
          "target.entity": "Category",
          "source.fields": [ "category_id" ],
          "target.fields": [ "id" ]
        }
      }
    },
    "Category": {
      "source": {
        "type": "table",
        "object": "dbo.categories"
      },
      "relationships": {
        "category_books": {
          "cardinality": "many",
          "target.entity": "Book",
          "source.fields": [ "id" ],
          "target.fields": [ "category_id" ]
        }
      }
    }
  }
}

See also

Concept REST GraphQL Purpose
Projection $select items Choose which fields to return
Filtering $filter filter Restrict rows by condition
Sorting $orderby orderBy Define the sort order
Page size $first first Limit the number of items per page
Continuation $after after Continue from the last page using a cursor

Note

REST keywords begin with $, following OData conventions.