Stargate Document API QuickStart

Time to complete: 5 minutes

Stargate is a data gateway deployed between client applications and a database. In this QuickStart, you’ll be up and running on your local machine with the Document API plugin that exposes CRUD access to data stored in Cassandra tables.

Prerequisites

If you are looking to just get started, DataStax Astra Database-as-a-Service can get you started with no install steps.

  • Install cURL, a utility for running REST, Document, or GraphQL queries on the command line.

  • [Optional] If you prefer, you can use Postman as a client interface for exploring the APIs

    • You will also find links to downloadable collections and environments in Using Postman

  • [Optional] If you going to use the GraphQL API, you will want to use the GraphQL Playground to deploy schema and execute mutations and queries.

  • [Optional] For the REST and Document APIs, you can use the Swagger UI.

  • Install Docker for Desktop

  • Pull a Stargate Docker image

  • Cassandra 4.0

  • Cassandra 3.x

  • DSE 6.8

This image contains the Cassandra Query Language (CQL), REST, Document, GraphQL APIs, and GraphQL Playground, along with an Apache Cassandra 4.0 backend.

docker pull stargateio/stargate-4_0:v1.0.57

This image contains the Cassandra Query Language (CQL), REST, Document, GraphQL APIs, and GraphQL Playground, along with an Apache Cassandra 3.11 backend.

docker pull stargateio/stargate-3_11:v1.0.57

This image contains the Cassandra Query Language (CQL), REST, Document, GraphQL APIs, and GraphQL Playground, along with a DataStax Enterprise 6.8 backend.

docker pull stargateio/stargate-dse-68:v1.0.57
  • Run the Stargate Docker image

  • Cassandra 4.0

  • Cassandra 3.x

  • DSE 6.8

Start the Stargate container in developer mode. Developer mode removes the need to set up a separate Cassandra instance and is meant for development and testing only.

docker run --name stargate \
  -p 8080:8080 \
  -p 8081:8081 \
  -p 8082:8082 \
  -p 127.0.0.1:9042:9042 \
  -d \
  -e CLUSTER_NAME=stargate \
  -e CLUSTER_VERSION=4.0 \
  -e DEVELOPER_MODE=true \
  stargateio/stargate-4_0:v1.0.57

Start the Stargate container in developer mode. Developer mode removes the need to set up a separate Cassandra instance and is meant for development and testing only.

docker run --name stargate \
  -p 8080:8080 \
  -p 8081:8081 \
  -p 8082:8082 \
  -p 127.0.0.1:9042:9042 \
  -d \
  -e CLUSTER_NAME=stargate \
  -e CLUSTER_VERSION=3.11 \
  -e DEVELOPER_MODE=true \
  stargateio/stargate-3_11:v1.0.57

Start the Stargate container in developer mode. Developer mode removes the need to set up a separate DSE instance and is meant for development and testing only.

docker run --name stargate \
  -p 8080:8080 \
  -p 8081:8081 \
  -p 8082:8082 \
  -p 127.0.0.1:9042:9042 \
  -d \
  -e CLUSTER_NAME=stargate \
  -e CLUSTER_VERSION=6.8 \
  -e DEVELOPER_MODE=true \
  stargateio/stargate-dse-68:v1.0.57

Creating schema

In order to use the Document API, you must create schema that defines the namespace and collections that will store the data. A namespace is a container for which a replication factor defines the number of data replicas the database will store. Collections consist of unstructured JSON documents. Documents can themselves hold multiple documents. Multiple collections are contained in a namespace, but a collection cannot be contained in multiple namespaces.

Creating a namespace

In order to use the Document API, you must create the namespace as a container that will store collections, which in turn store documents. Documents can themselves hold multiple documents. Multiple collections are contained in a namespace, but a collection cannot be contained in multiple namespaces.

Only namespaces need to be specifically created. Collections are specified when a document is inserted. An optional setting, replicas, defines the number of data replicas the database will store for the namespace. If no replica is defined, then for a namespace in a single datacenter cluster, the default is 1, and for a multiple-datacenter cluster, the default is 3 for each datacenter.

Simple namespace

Send a POST request to /v2/schemas/namespaces. In this example we use test for the name, and no replicas setting, to default to 1. docs/build/stargate/stargate/develop/api-doc/doc-creating-namespace.html

  • cURL command (/v2)

  • Result

curl --location --request POST 'https://localhost:8082/v2/schemas/namespaces' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
    "name": "test"
}'
{"name":"test"}

The generated authorization token and the content type are passed with --header. The token must be identified as X-Cassandra-Token so that cluster recognizes the token and its value. The specified name for the namespace is passed as JSON data using --data.

cURL can use any of the shortcut or longhand flags:

Shortcut Longhand Example Description

-L

--location

-L https://localhost:8082

Retrieves the URL listed, even if it has moved

-X

--request

-X PUT

Defines the type of REST operation, such as POST, GET, and DELETE

-H

'--header'

'-H "X-Cassandra-Token: $AUTH_TOKEN"'

Passes header information, such as auth tokens and the content type

'-d'

'--data'

-d '{ "name": "test", "replicas": 1 }'

Passes data as part of the request body

'-g'

'--globoff'

No argument

The -globoff flag switches off the URL globbing parser, and you can specify URLs that contain the characters {}[] without having curl interpret them. This option is handy for making the URLs for Document API calls cleaner to read, with less escaping.

Creating a collection

In the Document API, collections are created in a {glossary_url}gloss_namespace.html[namespace]. Collections store documents. Multiple collections are contained in a namespace, but a collection cannot be contained in multiple namespaces.

Only namespaces need to be specifically created. Collections can be created either as an empty collection first, or created with the first document creation in a collection.

Creating an empty collection

Send a POST request to /v2/namespaces. In this example we use library for the name.

  • cURL command (/v2)

  • Result

curl --location \
--request POST 'https://localhost:8082/v2/namespaces/test/collections' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
  "name": "library"
}'
No return

The generated authorization token and the content type are passed with --header. The token must be identified as X-Cassandra-Token so that cluster recognizes the token and its value. The specified name for the namespace is passed as JSON data using --data.

cURL can use any of the shortcut or longhand flags:

Shortcut Longhand Example Description

-L

--location

-L https://localhost:8082

Retrieves the URL listed, even if it has moved

-X

--request

-X PUT

Defines the type of REST operation, such as POST, GET, and DELETE

-H

'--header'

'-H "X-Cassandra-Token: $AUTH_TOKEN"'

Passes header information, such as auth tokens and the content type

'-d'

'--data'

-d '{ "name": "test", "replicas": 1 }'

Passes data as part of the request body

'-g'

'--globoff'

No argument

The -globoff flag switches off the URL globbing parser, and you can specify URLs that contain the characters {}[] without having curl interpret them. This option is handy for making the URLs for Document API calls cleaner to read, with less escaping.

Add JSON schema to a collection

To set JSON schema that a collection’s documents will use, send a PUT request to /v2/namespaces/test/collections/library. In this example, a collection is created to store a Person object that has three properties: first name, last name, and age:

  • cURL command (/v2)

  • Result

curl --location --request PUT 'https://localhost:8082/v2/namespaces/test/collections/library2/json-schema' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json' \
--data-raw '{
  "title": "Person",
  "type": "object",
  "properties": {
    "firstName": {
      "type": "string",
      "description": "The person'\''s first name."
    },
    "lastName": {
      "type": "string",
      "description": "The person'\''s last name."
    },
    "age": {
      "description": "Age in years which must be equal to or greater than zero.",
      "type": "integer",
      "minimum": 0
    }
  }
}
'
{
  "schema": {
    "title": "Person",
    "type": "object",
    "properties": {
      "firstName": {
        "type": "string",
        "description": "The person's first name."
      },
      "lastName": {
        "type": "string",
        "description": "The person's last name."
      },
      "age": {
        "description": "Age in years which must be equal to or greater than zero.",
        "type": "integer",
        "minimum": 0
      }
    }
  }
}

JSON schema support is experimental. Also, partial updates of data are not allowed if JSON schema is defined.

Checking namespace existence

To check if a namespaces exist, execute a Document API query with cURL to find all the namespaces:

  • cURL command (/v2)

  • Result

curl -L -X GET 'https://localhost:8082/v2/schemas/namespaces' \
-H "X-Cassandra-Token: $AUTH_TOKEN" \
-H 'Content-Type: application/json'
{
  "data": [
    {
      "name": "system_schema"
    },
    {
      "name": "system"
    },
    {
      "name": "system_auth"
    },
    {
      "name": "system_distributed"
    },
    {
      "name": "system_traces"
    },
    {
      "name": "stargate_system"
    },
    {
      "name": "data_endpoint_auth"
    },
    {
      "name": "test"
    }
  ]
}

To get a particular namespace, specify the namespace in the URL:

  • cURL command (/v2)

  • Result

curl -X GET 'https://localhost:8082/v2/schemas/namespaces/test' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json'
{
  "data": {
    "name": "test"
  }
}

Deleting a namespace

Send a DELETE request to /v2/schemas/namespaces/{namespace_name} to delete a namespace. All collections and documents will be deleted along with the namespace.

curl -L -X DELETE 'https://localhost:8082/v2/schemas/namespaces/test' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json'
Deletions do not return any data.

Writing documents

All data written with the Document API is stored as JSON documents stored in collections.

A few terms will help your understanding as you prepare to write and read documents:

document-id

An ID that you can either assign as a string when creating a document, or a random UUID that is assigned if an ID is not assigned during document creation.

document-path

An endpoint (resource) that exposes your API, such as /book or /book/genre.

operation

An HTTP method used to manipulate the path, such as GET, POST, or DELETE.

For more information about the database design of the Document API, see the blog post on the Documents API.

Add document with a document-id

First, let’s add a document to a specified collection using a document-id. If a document-id is specified, a PUT request is required, rather than a POST request. The document-id can be any string. Send a PUT request to /v2/namespaces/{namespace_name}/collections/{collection_name}/{document-id} to add data to the collection library. The data is passed in the JSON body.

  • cURL command (/v2)

  • Result

curl --location \
--request PUT 'https://localhost:8082/v2/namespaces/test/collections/library/2545331a-aaad-45d2-b084-9da3d8f4c311' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
  "stuff": "2545331a-aaad-45d2-b084-9da3d8f4c311",
  "other": "I need a document with a set value for a test."
}'
{
  "documentId": "2545331a-aaad-45d2-b084-9da3d8f4c311"
}

Notice that the document-id is returned.

Add a document without a document-id

Suppose you want each document to be assigned a random UUID. Send a POST request to /v2/namespaces/{namespace_name}/collections/{collections_name} to add data to the collection library. The data is passed in the JSON body.

  • cURL command (/v2)

  • Result

curl --location \
--request POST 'https://localhost:8082/v2/namespaces/test/collections/library' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
  "id": "some-stuff",
  "other": "This is nonsensical stuff."
}'
{
  "documentId": "0c88a952-ea0b-4000-83ba-57d293b8e345"
}

Notice that the document-id returned is a UUID if not specified, by default.

Add a document with data

Documents can be added with varying JSON data, unless a JSON schema is specified. Send a POST request to /v2/namespaces/{namespace_name}/collections/{collections_name} similar to the last example, but add more JSON data to the body of the request:

  • cURL command (/v2)

  • Result

curl --location --request POST 'https://localhost:8082/v2/namespaces/test/collections/library' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json' \
--data-raw ' {
    "reader": {
       "name": "Amy Smith",
       "user_id": "12345",
       "birthdate": "10-01-1980",
       "email": {
           "primary": "asmith@gmail.com",
           "secondary": "amyispolite@aol.com"
       },
       "address": {
           "primary": {
               "street": "200 Antigone St",
               "city": "Nevertown",
               "state": "MA",
               "zip-code": 55555
           },
           "secondary": {
               "street": "850 2nd St",
               "city": "Evertown",
               "state": "MA",
               "zip-code": 55556
           }
       },
       "reviews": [
           {
               "book-title": "Moby Dick", 
               "rating": 4, 
               "review-date": "04-25-2002",
               "comment": "It was better than I thought."
           },
           {
               "book-title": "Pride and Prejudice", 
               "rating": 2, 
               "review-date": "12-02-2002",
               "comment": "It was just like the movie."
           }
       ]
    }
}'
{
  "documentId": "9a47dcbc-2a41-429e-bd1b-fad26ac23b00"
}

Note the difference between using POST and PUT. The POST request is used to insert new documents when you want the system to auto-generate the document-dd. The PUT request is used to insert a new document when you want to specify the document-id. These commands can also be used to update existing documents.

A 'PATCH' request using a document-id will replace the targeted data in a JSON object contained in the document. JSON objects are delimited by { } in the data. If you have an array, delimited by '[ ]' in the JSON object targeted, or a scalar value, the values will be overwritten.

For more information about the database design of the Document API, see the blog post on the Documents API.

Retrieving a document from a collection with a document-id

Retrieving a specified document

Let’s check that some data was inserted for a particular document. Send a GET request to /v2/namespaces/{namespace_name}/collections/{collections_name}/{document-id} to retrieve the document:

  • cURL command (/v2)

  • Result

curl -L \
-X GET 'https://localhost:8082/v2/namespaces/test/collections/library/2545331a-aaad-45d2-b084-9da3d8f4c311' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json'
{
  "documentId": "2545331a-aaad-45d2-b084-9da3d8f4c311",
  "data": {
    "okaydokie": "Now I have done it! We have a TTL at last!"
  }
}

Search for information within documents

Retrieving a specific portion of a document with document-path

A document-path uses a document’s structure to drill down and get information from within a document. To find particular values, send a GET request to /v2/namespaces/{namespace_name}/collections/{collections_name}/{document-id}/{document-path} to retrieve a book title:

  • cURL command (/v2)

  • Result

curl --location --request GET 'https://localhost:8082/v2/namespaces/test/collections/library/native-son-doc-id/book/title' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json' \
{
  "documentId": "native-son-doc-id",
  "data": "Native Son"
}

Retrieving a document field value using a document-path and array number

This example shows the use of an array value, in conjunction with a document-id and document-path, to find the book-title of the second book a reader reviewed:

  • cURL command (/v2)

  • Result

curl --location -g --request GET 'https://localhost:8082/v2/namespaces/test/collections/library/John-Smith/reader/reviews/[1]' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json' \
{
  "documentId": "John-Smith",
  "data": {
    "book-title": "Pride and Prejudice",
    "comment": "It was a wonderful book! I loved reading it.",
    "rating": 5,
    "review-date": "03-02-2002"
  }
}

Retrieving document data using a document-path and WHERE clause

This example shows the use of a WHERE clause, in conjunction with a document-id and document-path:

  • cURL command (/v2)

  • Result

curl --location -g --request GET 'https://localhost:8082/v2/namespaces/test/collections/library/John-Smith/reader/reviews?WHERE={"reader.reviews.rating":{"$eq":5}' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json' \
{
  "documentId": "John-Smith",
  "data": [
    {
      "book-title": "Moby Dick",
      "comment": "It was okay.",
      "rating": 3,
      "review-date": "02-02-2002"
    },
    {
      "book-title": "Pride and Prejudice",
      "comment": "It was a wonderful book! I loved reading it.",
      "rating": 5,
      "review-date": "03-02-2002"
    }
  ]
}

Updating documents

Data changes, so often it is necessary to update or modify an entire document.

Replace a document with PUT

A PUT request using a document-id will replace a document found in a collection.

  • cURL command (/v2)

  • Result

curl --location --request PUT 'https://localhost:8082/v2/namespaces/test/collections/library/2545331a-aaad-45d2-b084-9da3d8f4c311' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json' \
--data-raw ' {
  "id": "some-other-stuff",
  "other": "This is changed nonsensical stuff."
}'
{
  "documentId": "2545331a-aaad-45d2-b084-9da3d8f4c311"
}

To check if the data is changed, GET the document:

  • cURL command (/v2)

  • Result

curl -L \
-X GET 'https://localhost:8082/v2/namespaces/test/collections/library/2545331a-aaad-45d2-b084-9da3d8f4c311' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json'
{
  "documentId": "2545331a-aaad-45d2-b084-9da3d8f4c311",
  "data": {
    "id": "some-other-stuff",
    "other": "This is changed nonsensical stuff."
  }
}

Replace some data in a document with PATCH and document-id

A 'PATCH' request using a document-id will replace the targeted data in a JSON object contained in the document. JSON objects are delimited by { } in the data. If you have an array, delimited by '[ ]' in the JSON object targeted, or a scalar value, the values will be overwritten.

  • cURL command (/v2)

  • Result

curl --location --request PATCH 'https://localhost:8082/v2/namespaces/test/collections/library/2545331a-aaad-45d2-b084-9da3d8f4c311' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json' \
--data-raw ' {
  "yet-another-field": "Hopefully, I haven'\''t lost my other two fields!"
}'
{
  "documentId": "2545331a-aaad-45d2-b084-9da3d8f4c311"
}

To check if the data is changed, GET the document:

  • cURL command (/v2)

  • Result

curl -L \
-X GET 'https://localhost:8082/v2/namespaces/test/collections/library/2545331a-aaad-45d2-b084-9da3d8f4c311' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json'
{
  "documentId": "2545331a-aaad-45d2-b084-9da3d8f4c311",
  "data": {
    "id": "some-other-stuff",
    "other": "This is changed nonsensical stuff.",
    "yet-another-field": "Hopefully, I haven't lost my other two fields!"
  }
}

PATCH updates are upserts. If the document doesn’t exist, it will be created. If it does exist, it will be updated with the new document data.

Another example with PATCH

  • cURL command (/v2)

  • Result

curl --location --request PATCH 'https://localhost:8082/v2/namespaces/test/collections/library/2545331a-aaad-45d2-b084-9da3d8f4c311' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json' \
--data-raw ' {
  "yet-another-field": "Hopefully, I haven'\''t lost my other two fields!",
  "languages": [
     "English",
     "German",
     "French"
  ]
}'
{
  "documentId": "2545331a-aaad-45d2-b084-9da3d8f4c311"
}

To check if the data is changed, GET the document:

  • cURL command (/v2)

  • Result

curl -L \
-X GET 'https://localhost:8082/v2/namespaces/test/collections/library/2545331a-aaad-45d2-b084-9da3d8f4c311' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json'
{
  "documentId": "2545331a-aaad-45d2-b084-9da3d8f4c311",
  "data": {
    "id": "some-other-stuff",
    "languages": [
      "English",
      "German",
      "French"
    ],
    "other": "This is changed nonsensical stuff.",
    "yet-another-field": "Hopefully, I haven't lost my other two fields!"
  }
}

Delete a document or part of a document

Delete data in a document

To delete a document path in a document, send a DELETE request to /v2/namespaces/{namespace_name}/collections/{collections_name}/{document-id}/{document-path}. In this example, the secondary address for the user John Smith is deleted from the document.

curl --location -g --request DELETE 'https://localhost:8082/v2/namespaces/test/collections/library/John-Smith/reader/address/secondary' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json' \

Delete full document using a document-id

To delete a document, send a DELETE request to /v2/namespaces/{namespace_name}/collections/{collections_name}/{document-id}.

curl -L \
-X DELETE 'https://localhost:8082/v2/namespaces/test/collections/library/2545331a-aaad-45d2-b084-9da3d8f4c311' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json'
Deletions do not return any data.

Delete a full document using a WHERE clause

To delete a document, based on a WHERE clause, send a DELETE request to /v2/namespaces/{namespace_name}/collections/{collections_name}/{document-id}/?{where-clause}.

curl --location -g --request DELETE 'https://localhost:8082/v2/namespaces/test/collections/library/2545331a-aaad-45d2-b084-9da3d8f4c311?where={ "id":{"$eq":"some stuff"}}' \
--header "X-Cassandra-Token: $AUTH_TOKEN" \
--header 'Content-Type: application/json' \

Voila! For more information on the Document API, see the Using the Document API or the Document API in the API references section.