Dark Mode

DataStax Astra DB uses the Stargate GraphQL API to easily modify and query yourtable data using GraphQL types, queries, and mutations.

The schema-first approach allows you to create idiomatic GraphQL types, mutations, and queriesin a manner familiar to GraphQL developers.The schema is deployed and can be updated by deploying a new schema withoutrecreating the tables and columns directly.Under the covers, this approach will create and modify the CQL tables to matchthe GraphQL types.The schema can be modified for CQL decorated schema, such as specifying tableand column names in Cassandra,while retaining GraphQL-centric names for the types that correspond.If you are a GraphQL developer, this approach is for you.

To use Stargate with Astra DB you need to:

  • Register for Astra DB.
  • Create a database after you log into your Astra account.
  • Generate an application token to use the GraphQL Playground and cURL.
  • Run GraphQL Playground to deploy schema,and execute mutations and queries.
  • Optional: cURL to run GraphQL queries from command-line.
  • Optional: Postman collections if you wish to execute mutations and queries inPostman.

User-defined types (UDTs) can be created as GraphQL object types.UDTs are optional, but if you wish to use a UDT in another object type definition,you'll want to create the UDT first.Once created, you can include the type in the schema deployed via the GraphQL playground.

Prerequisites

Here are two examples that create a UDT called Address that includes a street, city, state, and zipcode,and a UDT called Review that includes a book title, comment, rating and review data.

Directives in example:

Prerequisites

Use the application token you generatedto create schema in your keyspace using the GraphQL playground.

Object types

The most basic components of a GraphQL schema are object types, which justrepresent a kind of object you can fetch from your service, and specify thefields contained in the object.Object types also havedirectives, whichare identifiers preceded by an `@` character.Directives are GraphQL server-specific, and implemented in the server.Stargate implements directives that are specific to the Apache Cassandrabackend, as well as Apollo data federation-specific directives that allow Stargateto work with the Apollo gateway.

Directives in example:

The fields author , reviews , address are defined as arrays by the addition of square brackets,`reviews: [Review] .Note that reviews and addresses are arrays of UDTswhereas author` is a list of Strings to name each author.

Create queries

Most types in your schema will just be normal object types, but there are two typesthat are special, the Query type and the Mutation type.Every GraphQL service has at least one query type.Mutation types are optional.

Queries

Create mutations

Mutations work in a similar way to queries.An input and output is defined.

The insert mutation will insert an object of the specified type, and the update and delete mutations will return a Boolean value.If the update or delete mutation names begin with those words, the `@cql_update` directiveis not required.

Conditional insertion

A mutation can be turned into a conditional insertion operation by ending the mutationname with ifNotExists .However, it may be useful to know if the insertion is successfully applied.In that case, see payload type below to see how a boolean field applied canbe added to the response from insertions or annotating it with `@cql_insert(ifNotExists: true)`.

Create payload types

Payloads types are not mapped to the database, and only serve as wrappers of an operation's response.They typically pass a more complex object than just an entity. For example,you can add fields that check the applied status for a conditional query, orthe pagingState .

In this example, a payload type SelectBookResult is created that accepts an arrayof books as the input. The associated query can use the required title and optional pagingState as input, and will return an array of books along with the pagingState .

Directives in example:

An example of retrieving data using this query is found xref:graphql-using-schema-first#retrievingdata[below].

Often, you wish to know if an operation was successful. Creating a payload type thatuses a boolean field applied can definitively answer if a conditional operationcompletes correctly.

Create a payload type that uses your standard object type as a field, along with applied :

If the conditional insert is successful (the row did not exist), then appliedwill be true and book will echo back the data that was just inserted;otherwise, applied will be false and book will be the existing data.

Creating indexes

Prerequisites

Use the application token you generatedto create schema in your keyspace using the GraphQL playground.

Cassandra supports indexing any regular, non-primary key fields in an object type.Any field designated as a partition key or clustering column cannot be indexed,unless DataStax Enterprise is the defined database.A field will be indexed if `@cql_index` is added to the field definition.Indexed fields can be used as parameters in queries.

The directive `@cql_index` has the following optional arguments:

ArgumentDefaultDescription
nameGeneratedCustom index name.
classSecondary indexCustom index class, such as SAI.
targetVALUESSpecifies set and list index type. Options are FULL and VALUES.
optionsN/AAny options to pass to the underlying index query.

Prerequisites

Use the application token you generatedto create schema in your keyspace using the GraphQL playground.

Deploying schema manually

Now that you have created GraphQL types, queries, and mutations, it's time to deploy the schema.Recall that the corresponding CQL schema is inferred and created from the GraphQL schemasubmitted.

A keyspace will be created as CQL-first unless a schema is deployed.After a schema is deployed, the keyspace should be accessed as schema-first.

Inside the GraphQL playground, navigate to http://$ASTRACLUSTERID-$ASTRA_REGION.apps.astra.datastax.comundefined` and createthe schema to deploy to a previously defined keyspace:

A defined mutation deploySchema is executed.The keyspace is specified, along with the schema, specified between triple quotes ( """ ).

A number of additional options are used in the following manner:

OptionDefaultDescription
expectedVersionN/AEach schema is assigned a unique version number. If the current deployment is a modification, the version must be supplied.
dryRunfalseTo test in a dryrun, use dryRun: true
forcefalseForce a schema change
migrationStrategyADDMISSINGTABLESANDCOLUMNSUSE_EXISTING, ADDMISSINGTABLES, ADDMISSINGTABLESANDCOLUMNS, DROPAND_RECREATEALL, DROPANDRECREATEIFMISMATCH

Two items are returned in this example, the version that is assigned to the schema,and cqlChanges , the status of whether CQL changes occurred due to the schema deployment.Other responses are logs and query .

The migrationStrategy option needs further explanation on how deploySchema updates the underlying CQL schema, based on the options argument.The available strategies are:

Deploy schema file using cURL

Schema can also be deployed to a keyspace using a schema file upload.This mutation must be executed with a multipart request (note that your operations part must declare MIME type application/json).

In this case, deploySchemaFile is executed. This query must be executed in the command linewith a cURL command:

The operations part contains the GraphQL payload. It consists of aparameterized mutation, which takes a single $file argument (note that we leave it as null in the payload, because it's going to be set another way).The filePart argument contains the file.The map argument specifies that the file specified by filePart will mapto the variables.file setting.In this example, the schema file supplied is located in /tmp/schema.graphql .

In order to deploy a schema file again, you'll need to supply the expectedVersion for the schema to be replaced.Check the keyspace schemato get the current version.

Modify schema

To modify the current schema, simply deploy again, supplying the expectedVersion as thecurrent schema's version if you wish to overwrite the definitions.Otherwise, a new schema with a new version id will be created.Either the GraphQL Playground or the cURL command can be used to update the schema.

Check the keyspace schema

To check if the schema exists, execute a GraphQL check in http://$ASTRACLUSTERID-$ASTRA_REGION.apps.astra.datastax.comundefined`:

For all versions of a keyspace schema:

Note that the result lists the current schema version for every loaded schema.

For a particular version of a keyspace schema:

To undeploy an existing schema, use the following mutation.

The keyspace name and schema version must be supplied.One option is available, force , to force an erasure of the schema.

Inserting data

Prerequisites

If you have created schema for insertion, now you are ready to write data into the database.

First, let's navigate to your new keyspace library inside the playground.Change the location to http://$ASTRACLUSTERID-$ASTRA_REGION.apps.astra.datastax.com/api/graphql/library and add a couple of books to the book table:

The insertion is straightforward.The title and author are specified, and the title is returned in response to a successful insertion.Only the required fields must be specified, and any fields can be returned in the response.This same operation can update stored data, as insertions are upserts in all cases.

Conditional insertion

Insert arrays and UDTs

Inserting arrays and UDTs requires a few extra embellishments:

Note the use of square brackets around arrays of objects, with commas separatingarray items.

Prerequisites

Let's check that the data was inserted.Use the query book with the primary key to find a book based on its title.Use http://$ASTRACLUSTERID-$ASTRA_REGION.apps.astra.datastax.com/api/graphql/library to execute the query in GraphQL playground:

It is also possible to find books with a partial primary key. If more than one bookhas the same title (partition key), for instance, but different ISBN codes (clustering key),then a listing of all books that match can be retrieved:

In both queries, the title , isbn , and author are specified as return results.

To display the contents of a UDT, notice the inclusion of addresses and itsembedded fields in the values designated as return values in this query to retrieve the readers:

In this example, the primary key consists of both name and user_id , to distinguishreaders who might have the same name.

Stargate only allows combinations of fields that have:

  • at most one indexed field in the query
  • if no indexed field is present, then all partition key fields must be present
  • it's possible to omit some or all of the clustering fields (in which casethe query may return multiple rows)

'Filter options for reads'

It's possible to customize the CQL condition of each parameter with `@cql_where`with the following arguments:

  • field: the GraphQL field name to which the condition applies
  • predicate: the conditional predicate to use

The filters available are:

PredicateGraphQL fields that can have condition applied
EQ (equal)partition key, clustering key, regular indexed field
IN (within)partition key, clustering key, regular indexed field
GT (greater than)clustering key
GTE (greater than or equal to)clustering key
LT (less than)clustering key
LTE (less than or equal to)clustering key
CONTAINSregular indexed field that is a list and has an index target of VALUES

IN example, that finds the books that are listed in the supplied array:

IN example with 2 partition keys, demonstrating that values for eachcan be supplied:

GT example, that looks for equality on the partition key, and then a range ofpossible values for the clustering field:

GT example #2, that looks for a book with a title and an ISBN code that isgreater than the value supplied:

LT example, that looks for a book with the same title and an ISBN code that isless than the value supplied:

CONTAINS example that shows how to retrieve a reader that submitted asupplied review:

Updating data

Prerequisites

A mutation can be turned into a update operation by starting the mutationname with update .A mutation will also be an update operation if it is annotated with `@cql_update`.The mutation must take a single argument that is an input type for a mapped entity.If successful, the mutation will return a Boolean value.In order to execute the mutation, all primary key fields and at least one non-primary keyfield must be input.

For example, the following mutation and associated query will update a single row:

Updates are upserts. If the row doesn't exist, it will be created.If it does exist, it will be updated with the new row data.

Deleting data

Prerequisites

A mutation can be turned into a delete operation by starting the mutationname with delete or remove .A mutation will also be a delete operation if it is annotated with `@cql_delete`.The mutation must take a single argument that is an input type for a mapped entity,or individual primary key arguments like retrieving operations.If successful, the mutation will return a Boolean value.

At runtime, all partition key fields must be present, and a prefix of theclustering columns can be present (if using a single object argument, other fields will be ignored).The delete operation targets a single row if it operates on a full primary key,or multiple rows otherwise.

Let's add another book "Pride and Prejudice" with an `insertBook()`, so that you can deletethe book using `deleteBook()` to illustrate deleting data:

To check for the existence of a record before deleting, use either method discussed above.This example shows the use of the directive `@cql_delete( ifExists: true)`:

  • 1