Developing with the Astra DB Document API
The Stargate Document API modifies and queries data stored as unstructured JSON documents in collections. Because the Document API uses schemaless data, no data modeling is required!
If the Document API is used with Apache Cassandra, the document indexing is accomplished with secondary indexes. If the Document API is used with DataStax Enterprise, SAI indexing is used. The blog The Stargate Cassandra Documents API describes the underlying structure used to store collections.
Information about namespaces and collections.
To use the Document API, you must define the namespace that will store collections. Collections store 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.
Only namespaces need to be specifically created. Collections are specified when a document is inserted.
Prerequisites
If you haven’t already, create a database using Astra DB. |
You can create an Astra DB database using Astra Portal or the DevOps API. Currently, there are no drivers or other APIs that support creating a database. |
-
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.
Before you get started, set your environment variables to save time developing on your database. There are four environment variables, three of which you will get from the Astra dashboard (database id, region, and keyspace), and one that you must create (token).
-
In Astra DB, select the database to which you want to connect.
-
In your Database Dashboard, select Connect.
-
Select your API.
If you have multiple regions, select the region you want to connect to from the dropdown menu for instructions.
-
Follow the steps to get your application token and set up your environment variables. Or if you have an older Astra Classic database, follow the steps in Authentication for classic databases.
API reference
If you prefer to learn using a QuickStart, try out the Stargate Document QuickStart. To view the API Reference, see Astra DB Document API.
Create namespace
See Adding a new keyspace to add a new namespace, or keyspace as it is known in Astra.
Checking namespace existence
To check if a namespaces exist, execute a
Document API query with cURL
to find all the namespaces:
curl -L -X GET 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com//api/rest/v2/schemas/namespaces' \
-H "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
-H 'Content-Type: application/json'
{"data":[{"name":"system_distributed"},{"name":"system"},
{"name":"data_endpoint_auth"},{"name":"system_schema"},{"name":"myworld"},
{"name":"stargate_system"},{"name":"system_auth"},{"name":"system_traces"}]}
To get a particular namespace, specify the namespace in the URL:
Writing documents
All data written with the Document API is stored as JSON documents stored in collections.
For more information about the database design of the Document API, see the blog post on the Documents API. |
Add document specifying a collection name
First, let’s add a document to a specified collection.
Send a POST
request to /api/rest/v2/namespaces/{namespace_name}/collections/{collections_name}
to add data to the collection fitness
.
The data is passed in the JSON body.
curl --location \
--request POST 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"id": "some-stuff",
"other": "This is nonsensical stuff."
}'
{"documentId":"{docid}"}
Notice that the document-id
returned is a UUID if not specified.
Add document specifying collection name and document-id
Next, let’s add a document to a specified collection, but specify the document-id
.
Send a PUT
request to
/api/rest/v2/namespaces/{namespace_name}/collections/{collections_name}/{document-id}
to add data to the collection Janet
.
The document-id
can be any string.
The data is passed in the JSON body.
curl -L -X PUT 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness/Janet' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"firstname": "Janet",
"lastname": "Doe",
"email": "janet.doe@gmail.com",
"favorite color": "grey"
}'
{"documentId":"Janet"}
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
documentId. The PUT
request is used to insert a new document when you want to
specify the documentId.
PUT
requests can also be used to update an existing
document. Let’s look at those examples, next.
Inserting a sub-document
You can also insert documents that have nested values, or sub-documents.
Send a PUT
request to
/api/rest/v2/namespaces/{namespace_name}/collections/{collections_name}/{document-id}
to add data to the existing collection.
The data is passed in the JSON body.
curl -L -X PUT 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness/Janet' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"firstname": "Joey",
"lastname": "Doe",
"weights": {
"type": "bench press",
"weight": 150,
"reps": 15
}
}'
{"documentId":"Joey"}
Reading documents
Retrieving a specified document
Let’s check that the data was inserted for a particular document.
Send a GET
request to /api/rest/v2/namespaces/{namespace_name}/collections/{collections_name}/{document-id}
to retrieve the document:
curl -L \
-X GET 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness/{docid}' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json'
{
"documentId":"{docid}",
"data":{
"id":"some-stuff",
"other":"This is nonsensical stuff."
}
}
It is possible to get a value for a particular field in a document using one of
two methods, either a where
clause or a document-path
. These methods can
retrieve information from a document or a sub-document.
Retrieving a document using a where clause
Now let’s search for a particular document using a where
clause.
Send a GET
request to
/api/rest/v2/namespaces/{namespace_name}/collections/{collections_name}?{where-clause}
to get the same information:
curl -L -X GET 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness?where=\{"firstname":\{"$eq":"Janet"\}\}' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json'
{
"data":{
"Janet":{
"email":"janet.doe@gmail.com",
"favorite color":"grey",
"firstname":"Janet",
"lastname":"Doe"
}
}
}
Note that the where
clause must be url encoded, so curly brackets are escaped
with \
and spaces must be replaced with %20
.
Also, the full document is returned, as opposed to the value of the field specified in the
{document-path}
like the next command.
Read with where
You can also search with a multiple where
clause.
Send a GET
request to
/api/rest/v2/namespaces/{namespace_name}/collections/{collections_name}?{where-clause}
to get the same information:
curl -L -X GET 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness?where=\{"firstname":\{"$eq":"Janet"\},"lastname":\{"$eq":"Doe"\}\}' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json'
{
"data":{
"Janet":{
"email":"janet.doe@gmail.com",
"favorite color":"grey",
"firstname":"Janet",
"lastname":"Doe"
}
}
}
Note that the where
clause must be url encoded, so curly brackets are escaped
with \
and spaces must be replaced with %20
.
Also, the full document is returned, as opposed to the value of the field specified in the
{document-path}
like the next command.
You can also retrieve documents using a WHERE
clause that searches sub-documents:
curl -L -X GET 'lhttps://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness?where=\{"weights.type":\{"$eq":"bench%20press"\}\}' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json'
{
"data":{
"Joey":{
"firstname":"Joey",
"lastname":"Doe",
"weights":{
"reps":15,
"type":"bench press",
"weight":150
}
}
},
"pageState":null
}
Multiple where
can be used in a variety of cases.
Here, a numerical value between to values is sought:
curl -L -X GET 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness?where=\{"weights.reps":\{"$gt":12\},"weights.reps":\{"$lt":20\}\}' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json'
{
"data": {
"Joey": {
"firstname": "Joey",
"lastname": "Doe",
"weights": {
"reps": 15,
"type": "bench press",
"weight": 150
}
}
}
}
Retrieving all documents
Let’s check that the document was inserted. Send a GET
request to
/api/rest/v2/namespaces/{namespace_name}/collections/{collections_name}
to retrieve
all the documents:
curl --location \
--request GET 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness?page-size=3' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json'
{
"data":{
"Joey":{
"firstname":"Joey",
"lastname":"Doe",
"weights":{
"reps":15,
"type":"bench press",
"weight":150
}
},
"Janet":{
"email":"janet.doe@gmail.com",
"favorite color":"grey",
"firstname":"Janet",
"lastname":"Doe"
},
"{docid}":{
"id":"some-stuff",
"other":"This is nonsensical stuff."
}
}
}
The page-size
parameter is included to get all the documents, rather than the
last inserted document.
Retrieving all documents with Paging
For large collections, you can page a subset of the results. In this example, page-size is set to 5. Send a GET request to /api/rest/v2/namespaces/{namespace_name}/collections/{collections_name}page-size=5 to retrieve the first five documents (a page) in the collection:
curl --location \
--request GET 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness?page-size=5' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json'
{
"pageState":"JGNlYjczMDc5LTE1NTItNGQyNS1hM2ExLWE2MzgxNWVlYTAyMADwf_____B_____",
"data":{
"58b12778-0efd-466e-89bf-66a4c99adee1":{"author":"Tom Clancy","title":"Red Rabbit"},
"77fe8690-f8d4-43b8-b1c9-a328318d4eae":{"author":"Tom Clancy","title":"Every Man a Tiger"},
"3177f86c-a633-4302-92a5-de4c15ab5840":{"author":"Tom Clancy","title":"Rainbow Six"},
"cefc7117-fc73-47b8-a965-099cf3a59269":{"author":"Tom Clancy","title":"Clear and Present Danger"},
"ceb73079-1552-4d25-a3a1-a63815eea020":{"author":"Tom Clancy","title":"The Cardinal of the Kremlin"}
}
}
Pay close attention to the pageState
value in the results. The pageState
is
a string representation a location in the result set. It is essentially an encoded
shortcut that allows the final result set to be built from a specific point.
In order to get the next five documents, re-run the request with page-state parameter set to the first page’s pageState:
curl -L -X GET 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness/Joey/weights/type' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json'
{"documentId":"Joey","data":"bench press"}
In this case, the sub-document weights
is the
document-path
specified to retrieve that data about the reps
, type
, and
weight
.
curl --location --request GET 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness/Joey/weights' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json'
{
"documentId":"Joey",
"data":{
"reps":15,
"type":"bench press",
"weight":150
}
}
Retrieving a specific portion of a document with document-path
Let’s add another record for the next example:
curl -L -X PUT 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness/Martha' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"firstname": "Martha",
"lastname": "Smith",
"weights": {
"type": "bench press",
"weight": 125,
"reps": 12
}
}'
{"documentId":"Martha"}
To find particular values, send a GET
request to
/api/rest/v2/namespaces/{namespace_name}/collections/{collections_name}/{document-id}/{document-path}
to retrieve all the users that have, say, weight reps between 11 and 16:
curl -L -X GET 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness?where=\{"weights.*":\{"$gt":11\},"weights.*":\{"$lt":16\}\}&page-size=3' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header "Content-Type: application/json"
{
"data": {
"Joey": {
"firstname": "Joey",
"lastname": "Doe",
"weights": {
"reps": 15,
"type": "bench press",
"weight": 150
}
},
"Martha": {
"firstname": "Martha",
"lastname": "Smith",
"weights": {
"reps": 12,
"type": "bench press",
"weight": 125
}
}
}
}
Update documents
Data changes, so often it is necessary to update an entire document.
Replace a document
Send a PATCH
request to
/api/rest/v2/namespaces/{namespace_name}/collections/{collections_name}/{document-id}
to replace data to the existing collection. All fields included will be changed.
curl -L \
-X PATCH 'lhttps://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness/Janet' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"firstname": "JanetLee",
"lastname": "Doe"
}'
{"documentId":"Janet"}
A GET
request will show that the data has been replaced in the document:
curl -L -X GET 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness/Janet' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json'
{
"documentId":"Janet",
"data":{
"email":"janet.doe@gmail.com",
"favorite color":"grey",
"firstname":"JanetLee",
"lastname":"Doe"
}
}
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.
|
Replace part of of a document or sub-document
It is also possible to update only part of a document. To partially update, send
a PATCH
request to
/api/rest/v2/namespaces/{namespace_name}/collections/{collections_name}/{document-id}/{document-path}
.
In this example, we want to change just the firstname of the document:
curl -L \
-X PATCH 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness/Janet' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"firstname": "Joseph"
}'
{"documentId":"Joey"}
and a GET
will show that only the weights
has been changed.
curl -L \
-X GET 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness/Joey' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json'
{
"documentId":"Joey",
"data":{
"firstname":"Joseph",
"lastname":"Doe",
"weights":{
"reps":15,
"type":"bench press",
"weight":150
}
}
}
To partially update a sub-document, send a PATCH
request to
/api/rest/v2/namespaces/{namespace_name}/collections/{collections_name}/{document-id}/{document-path}
in the same manner as the last command, but including only sub-document
information to change and the document-path
of the sub-document. Include
all fields that you wish to update.
curl -L \
-X PATCH 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness/Janet/weights' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"reps": 10,
"type": "squat",
"weight": 350
}'
{"documentId":"Joey"}
and a GET
will show that only the weights
has been changed.
curl -L \
-X GET 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness/Joey' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json'
{
"documentId":"Joey",
"data":{
"firstname":"Joseph",
"lastname":"Doe",
"weights":{
"reps":10,
"type":"squat",
"weight":350
}
}
}
Delete a document
To delete a document, send a DELETE
request to
/api/rest/v2/namespaces/{namespace_name}/collections/{collections_name}/{document-id}
.
curl -L \
-X DELETE 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness/{docid}' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json'
To delete a document, based on a document path, send a DELETE
request to
/api/rest/v2/namespaces/{namespace_name}/collections/{collections_name}/{document-id}/{document-path}
.
curl -L -X DELETE 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness?where=\{"id":\{"$eq":"some%2Dstuff"\}\}' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json'
Delete a collection
Send a DELETE
request to /api/rest/v2/namespaces/namespaces/{namespace_name}/collections/{collection_name}
to delete a collection. All data will be deleted along with the collection schema.
curl -L \
-X DELETE 'https://$ASTRA_CLUSTER_ID-$ASTRA_REGION.apps.astra.datastax.com/api/rest/v2/namespaces/myworld/collections/fitness' \
--header "X-Cassandra-Token: $ASTRA_DB_APPLICATION_TOKEN" \
--header 'Content-Type: application/json'
Document API Software Development Kit (SDK)
Node.js can be used with Astra to programmatically interact with your data using the Document API. An example of a client to work with collections is shown below:
Node.js Document Collection Client
Connect your app to DataStax Astra DB using the Document API in node.js.
The Astra DB Collection Node.js Client connects to the Astra DB Document API.
Set up your environment
-
Install the Astra DB JS Collection:
npm install @astrajs/collections
-
Open a browser, navigate to DataStax Astra, and log in.
-
From your Dashboard page, select your database.
-
Copy the Cluster ID of your database.
You can also find the Cluster ID in the URL, which is the last UUID in the path:
https://astra.datastax.com/org/{org-Id}/database/{databaseid}
-
Add the Cluster ID as an environment variable with the following command:
export ASTRA_DB_ID={databaseid}
Example:
export ASTRA_DB_ID=b5285f63-8da5-4c6e-afd8-ade371a48795
-
Copy the Region of your database, the region where your database is located.
-
Add the Region as an environment variable with the following command:
export ASTRA_DB_REGION={region}
Example:
export ASTRA_DB_REGION=us-east1
-
Add your username and your password as environment variables with the following command:
export ASTRA_DB_APPLICATION_TOKEN={token}
-
Use
printenv
to ensure the environment variables were exported.
Use Client with Nodejs
Document API
const { createClient } = require("@astrajs/collections");
// create an {astra_db} client
const astraClient = await createClient({
astraDatabaseId: process.env.ASTRA_DB_ID,
astraDatabaseRegion: process.env.ASTRA_DB_REGION,
applicationToken: process.env.ASTRA_DB_APPLICATION_TOKEN,
});
// create a shortcut to the users collection in the app namespace/keyspace
// collections are created automatically
const usersCollection = astraClient.namespace("app").collection("users");
// get a single user by document id
const user = await usersCollection.get("cliff@wicklow.com");
// get a subdocument by path
const userBlogComments = await usersCollection.get("cliff@wicklow.com/blog/comments");
// search a collection of documents
const users = await usersCollection.find({ name: { $eq: "Cliff" } });
// find a single user
const user = await usersCollection.findOne({ name: { $eq: "dang" } });
// create a new document (a documentId is generated)
const user = await usersCollection.create({
name: "New Guy",
});
// create a new user (specifying documentId)
const user = await usersCollection.create("cliff@wicklow.com", {
name: "cliff",
});
// create a user subdocument
const user = await usersCollection.create("cliff@wicklow.com/blog", {
title: "new blog",
});
// partially update user
const user = await usersCollection.update("cliff@wicklow.com", {
name: "cliff",
});
// partially update a user subdocument
const userBlog = await usersCollection.update("cliff@wicklow.com/blog", {
title: "my spot",
});
// replace a user subdocumet
const userBlog = await usersCollection.replace("cliff@wicklow.com/blog", {
title: "New Blog",
});
// delete a user
const user = await usersCollection.delete("cliff@wicklow.com");
// delete a user subdocument
const userBlog = await usersCollection.delete("cliff@wicklow.com/blog");