This post is a part of a tutorial series for learning how to build an app with DataStax's Astra database. See all of the posts in this Better Botz series to start using Astra now.
In the last blog post, we configured an Express backend server on Node.js, and then connected to our Astra database using the DataStax Node.js driver. We retrieved data from our orders table, only to realize that it’s empty. Fear not! We’re going to remedy that situation in this post and also start using Glitch to expedite development of our ordering application for Better Botz.
Goal 1: Configure Glitch with your secure connect bundle
If you don’t already have a Glitch account, head over to Glitch and create an account. After you create an account, open this Better Botz project.
- In Glitch, open the Better Botz project.
- Select Remix to Edit in the upper right to make a copy of the project. When you remix a project on Glitch, you’re creating a copy of an existing project that you can edit. Think of it like forking a GitHub repository.
-
In your remixed project, drag or upload the secure connect bundle for your DataStax Astra database.
The secure connect bundle is added to your assets, but we need it in a safe location. Therefore, we’ll move it to a hidden directory.
-
In your remixed project, in the project navigator to the left, select New File.
- Enter
.data
and then select Add This File. The new.data
directory will not display in your project navigator, but is created as a hidden directory. - At the bottom of your project navigator, select Tools > Terminal to open the terminal for your project.
-
In the Glitch terminal for your project, change to your
.data
directory.
cd ~/.data
In your project navigator, choose your assets folder, right-click your secure connect bundle, and copy the URL of that file.
-
In the Glitch terminal, in the
.data
directory, use wget to download your secure connect bundle:
wget secure-connect-bundle-url
Replace
secure-connect-bundle-url
with the URL for your secure connect bundle that you copied in the previous step. Choose your assets folder, select your secure connect bundle, and delete it.
-
Rename your secure connect bundle to secure-connect.zip.
mv secure-connect-bundle-name secure-connect.zip
- Enter
Your secure connect bundle is now accessible in Glitch. Great job! Going through the extra work of putting your database credentials in a hidden directory is tedious, but ensures that your secure connect bundle is secure.
Goal 2: Adding order data
If you recall from the last post, we retrieved data from our orders table, only to discover that it was empty. To process customer orders, we need order data!
In previous posts, we created tables and inserted data using the Cassandra Query Language SHell (CQLSH) that is embedded in Astra. This practice is perfectly acceptable, but we’re not CQL experts and would rather use a more programmatic tool. Therefore, we’ll use the Astra Data API.
Creating an authorization token
The Getting Started tutorial in the Astra API documentation illustrates the steps to connect to and interact with your Astra database. Following those instructions, we’ll use cURL commands in this example. Use this cURL command as you work through the following steps to create an authorization token.
Tip: If you want to issue commands from your application, choose the API endpoint you want to work with, select your preferred language, and enter the required data for the endpoint. The example automatically updates with the values you enter, making it easy to copy and paste into your IDE.
curl --request POST \
--url https://{databaseid}-{region}.apps.astra.datastax.com/api/rest/v1/auth \
--header 'accept: */*' \
--header 'content-type: application/json' \
--header 'x-cassandra-request-id: {unique-UUID}' \
--data '{"username":"{database-user}","password":"{database-password}"}'
- In a browser, log in to DataStax Astra.
- Select the database you want to connect to.
- In the Astra URL, copy the
databaseid
of your database, which is the last UUID in the path:https://astra.datastax.com/org/{org-Id}/database/{databaseid}
- Select the database you want to connect to and copy the cloud region where your database lives. For example,
us-east1
. - Copy the username and password you entered when creating your database.
- In the Astra URL, copy the
- In the cURL example you copied previously, replace these values with the values for your database:
-
{databaseid}
with the UUID of your database, copied from the Astra URL. -
{region}
with the cloud region where your database is located, as listed on the Database Details page in Astra. For example,us-east1
. -
{unique-UUID}
with a randomly-generated UUID that is unique for the authorization request. -
{database-user}
is the username entered when you created your database. -
{database-password}
is the password for the specified username.
-
- From the command line, run the entire
cURL
command with the values for your database. \ An authorization token is returned: \{"authToken": "37396a44-dcb8-4740-a97f-79f0dba47973"}
- Copy the value of the authorization token, which you'll include when making requests to your database, such as creating tables, adding rows, or modifying columns. In this example, the authorization token value is
37396a44-dcb8-4740-a97f-79f0dba47973
.
Inserting data in your orders table
Now that you have an authorization token, use it to connect to your Astra database and submit queries. You pass this token with each query to ensure a secure connection to your Astra database.
Before we can insert data, there’s something missing from our table structure that we discovered when reviewing the order data. Each order has a quantity, but our orders table doesn’t have a column for that data.
We’ll use the add column endpoint of the DataStax Astra API to add a quantity
column.
-
Copy the following request, which you use to add a
quantity
column to theorders
table in yourbetterbotz
keyspace.
curl --request POST \ --url https://{databaseid}-{region}.apps.astra.datastax.com/api/rest/v1/keyspaces/{my_keyspace}/tables/orders/columns \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --header 'x-cassandra-request-id: {unique-UUID}' \ --header 'x-cassandra-token: {auth-token}' \ --data '{"static":false,"name":"quantity","typeDefinition":"int"}'
Replace the following values with the values for your database:
Replace
{databaseid}
with the UUID of your database, copied from the Astra URL.Replace
{region}
with the cloud region where your database is located, as listed on the Database Details page in Astra. For example,us-east1
.Modify
my_keyspace
to match the name of your keyspace, which isbetterbotz
if you followed the previous blog entries.Enter a
{unique-UUID}
for the request and the{auth-token}
you created earlier.Run the cURL call to add a
quantity
column to yourorders
table in the keyspace that you specified. If the call is successful, a message returns indicating:{"success":true}
Now that our table columns are updated, we’ll use the update rows endpoint to add data to our orders
table. Copy the following cURL command and replace the same variables as in the previous steps.
curl --request PUT \
--url https://{databaseid}-{region}.apps.astra.datastax.com/api/rest/v1/keyspaces/{my_keyspace}/tables/tableName/rows/Otto%20Octavius \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'x-cassandra-request-id: {unique-UUID}' \
--header 'x-cassandra-token: {auth-token}' \
--data '{"changeset":[{"column":"id","value":"e65063a7-fba3-41ba-84bb-740a01cacf5e"},{"column":"address","value":"2475 Shadow Ln. Stow, Ohio(OH), 44224"},{"column":"prod_id","value":"31047029-2175-43ce-9fdd-b3d568b19bb0"},{"column":"prod_name","value":"Heavy Lift Arms"},{"column":"description","value":"Heavy lift arms capable of lifting 1,250 lbs of weight per arm. Sold as a set."},{"column":"price","value":4199.99},{"column":"quantity","value":5},{"column":"sell_price","value":21000.96}]}'
In the --data
option of the call, we’ll use the changeset
parameter to define the data that we want to update in the orders
table. This example adds a single row to the orders table.
Notice that Otto%20Octavius
is used in the --url
option, but customer_name
is not included in the changeset. That’s because customer_name
is the primary key, which identifies the location and order of stored data. The first column declared in the primary key definition is the partition key, which we’ll get to in the next section when creating a shipping table.
To add more rows:
- Copy the
changeset
parameter for each of the following examples and replace thechangeset
defined by the--data
option of the call. - Replace the primary key in the the
--url
option to use the value indicated before the example. - Run the cURL command with the updated data.
For example, here’s an updated changeset
parameter for a customer named Desmond Blackwell. Because customer_name
is the primary key, the --url
changes to:
https://databaseid-region.apps.astra.datastax.com/api/rest/v1/keyspaces/keyspaceName/tables/tableName/rows/Desmond%20Blackwell
Primary key = Desmond%20Blackwell
'{"changeset":[{"column":"id","value":"e5a768fc-ffdd-49e9-a179-b491e024088a"},
{"column":"address","value":"91 Dogwood Dr. Bridgeport, Connecticut (CT) 06606"},
{"column":"prod_id","value":"31047029-2175-43ce-9fdd-b3d568b19bb8"},
{"column":"prod_name","value":"Precision Torso"},
{"column":"description","value":"Robot torso built to handle precision jobs with extra stability and accuracy reinforcement."},
{"column":"price","value":8199.99},
{"column":"quantity","value":3},
{"column":"sell_price","value":24599.97}]}'
Use the following examples to make additional update row calls by modifying the primary key, replacing the changeset, and running the cURL command again.
Primary key = Loretta%20Stillwell
'{"changeset":[{"column":"id","value":"fae7c26c-7bc4-41e0-9e9f-63905cc38944"},
{"column":"address","value":"1314 Lindwood Dr. Carter Lake, Iowa (IA) 51510"},
{"column":"prod_id","value":"31047029-2175-43ce-9fdd-b3d568b19bb7"},
{"column":"prod_name","value":"Medium Strength Torso"},
{"column":"description","value":"Robot body to handle general jobs."},
{"column":"price","value":1999.99},
{"column":"quantity","value":2},
{"column":"sell_price","value":3999.98}]}'
Primary key = Matt%20Williamson
'{"changeset":[{"column":"id","value":"02668188-7b74-4ac6-bb4b-273b14bbda7e"},
{"column":"address","value":"15900 Wilcox Ln. Marion, Michigan (MI) 49665"},
{"column":"prod_id","value":"31047029-2175-43ce-9fdd-b3d568b19bb6"},
{"column":"prod_name","value":"High Strength Torso"},
{"column":"description","value":"Robot body with reinforced plate to handle heavy workload and weight during jobs."},
{"column":"price","value":2999.99},
{"column":"quantity","value":6},
{"column":"sell_price","value":13199.94}]}'
Primary key = Jayashree%20Marshall
'{"changeset":[{"column":"id","value":"295c362d-2eaf-43c0-bd68-63efc2cd1767"},
{"column":"address","value":"107 Trulson St. Oakland, Nebraska (NE), 68045"},
{"column":"prod_id","value":"31047029-2175-43ce-9fdd-b3d568b19bb5"},
{"column":"prod_name","value":"Basic Task CPU"},
{"column":"description","value":"Head processor unit for robot with basic process tasks."},
{"column":"price","value":899.99},
{"column":"quantity","value":5},
{"column":"sell_price","value":4499.95}]}'
Primary key = Evelyn%20Davis
'{"changeset":[{"column":"id","value":"5305ff90-e838-46ea-860f-69e831d28146"},
{"column":"address","value":"36 Jasmine Ln. Valley Stream, New York(NY), 11581"},
{"column":"prod_id","value":"31047029-2175-43ce-9fdd-b3d568b19bb4"},
{"column":"prod_name","value":"High Process AI CPU"},
{"column":"description","value":"Head processor unit for robot with basic process tasks."},
{"column":"price","value":2199.99},
{"column":"quantity","value":12},
{"column":"sell_price","value":26399.88}]}'
Primary key = Wyatt%20Devonshire
'{"changeset":[{"column":"id","value":"bccaed73-e7fb-4f16-8799-206e08905161"},
{"column":"address","value":"2770 Raymond St. Forest Grove, Oregon(OR), 97116"},
{"column":"prod_id","value":"31047029-2175-43ce-9fdd-b3d568b19bb3"},
{"column":"prod_name","value":"Drill Arms"},
{"column":"description","value":"Arms for drilling into surface material. Sold as a set. Does not include drill bits."},
{"column":"price","value":2199.99},
{"column":"quantity","value":3},
{"column":"sell_price","value":6599.97}]}'
Primary key = Lavender%20Chesterfield
'{"changeset":[{"column":"id","value":"ccc5bc2d-d166-471b-ad44-68be45663545"},
{"column":"address","value":"250 Holmes Blvd #1A Gretna, Louisiana(LA), 70056"},
{"column":"prod_id","value":"31047029-2175-43ce-9fdd-b3d568b19bb1"},
{"column":"prod_name","value":"Precision Action Arms"},
{"column":"description","value":"Arms for precision activities in manufacturing or repair. Sold as a set."},
{"column":"price","value":12199.99},
{"column":"quantity","value":1},
{"column":"sell_price","value":12199.99}]}'
Primary key = Darius%20Smith
'{"changeset":[{"column":"id","value":"3c371be4-203c-497f-a1eb-79769d3526a8"},
{"column":"address","value":"199 State U Rd. Macks Creek, Missouri (MO), 65786"},
{"column":"prod_id","value":"31047029-2175-43ce-9fdd-b3d568b19bb2"},
{"column":"prod_name","value":"Medium Lift Arms"},
{"column":"description","value":"Medium lift arms capable of lifting 850 lbs of weight per arm. Sold as a set."},
{"column":"price","value":3199.99},
{"column":"quantity","value":1},
{"column":"sell_price","value":3199.99}]}'
Goal 3: Tracking orders being shipped
As orders propagate through the system, we’ll need to track ones that are shipping so that customers can easily check their order status. To that end, we’ll use the add table endpoint to create a shipping table in your Astra database.
-
Copy the following request, which you use to create a
shipping
table in yourbetterbotz
keyspace.On the last line of the following example,
shipping
is the table name. The table columns are defined bycolumnDefinitions
, such asid
,prod_id
,cust_id
, andaddress_id
.Remember the primary key we used earlier when updating the
orders
table? We also mentioned a partition key (partitionKey
), which is a special column that defines the outermost grouping of data, similar to a schema in a relational database. For theshipping
table, our partition key uses two columns:prod_name
andcustomer_name
.
curl --request POST \ --url https://{databaseid}-{region}.apps.astra.datastax.com/api/rest/v1/keyspaces/{my_keyspace}/tables \ --header 'accept: */*' \ --header 'content-type: application/json' \ --header 'x-cassandra-request-id: {unique-UUID}' \ --header 'x-cassandra-token: {auth-token}' \ --data '{"ifNotExists":true,"columnDefinitions":[ {"static":false,"name":"id","typeDefinition":"uuid"}, {"static":false,"name":"prod_id","typeDefinition":"uuid"}, {"static":false,"name":"cust_id","typeDefinition":"uuid"}, {"static":false,"name":"address_id","typeDefinition":"uuid"}, {"static":false,"name":"prod_name","typeDefinition":"text"}, {"static":false,"name":"customer_name","typeDefinition":"text"}, {"static":false,"name":"street","typeDefinition":"text"}, {"static":false,"name":"city","typeDefinition":"text"}, {"static":false,"name":"state","typeDefinition":"text"}, {"static":false,"name":"country","typeDefinition":"text"}, {"static":false,"name":"code","typeDefinition":"text"}], "primaryKey":{"partitionKey":["prod_name","customer_name"]}, "tableOptions":{"defaultTimeToLive":0},"name":"shipping"}'
Replace the following values with the values for your database:
Replace
{databaseid}
with the UUID of your database, copied from the Astra URL.Replace
{region}
with the cloud region where your database is located, as listed on the Database Details page in Astra. For example,us-east1
.Modify
my_keyspace
to match the name of your keyspace, which isbetterbotz
if you followed the previous blog entries.Enter a
{unique-UUID}
for the request and the{auth-token}
you created earlier.In the
--data
option of the call, we’ll define the table columns using thecolumnDefinitions
parameter.Run the cURL call to create a
shipping
table in the keyspace that you specified. If the call is successful, a message returns indicating:{"success":true}
Let’s use the get table endpoint to retrieve the table you just created. Replace the same variables as in previous steps, and then replace {tableName}
with the name of your table (which is shipping
).
curl --request GET \
--url https://{databaseid}-{region}.apps.astra.datastax.com/api/rest/v1/keyspaces/{keyspaceName}/tables/{tableName} \
--header 'accept: application/json' \
--header 'x-cassandra-request-id: {unique-UUID}' \
--header 'x-cassandra-token: {auth-token}'
Running this cURL command with the variables you entered returns data for your shipping table, but it’s not exactly human readable. You can add a pipe character and json_pp
at the end of your cURL command to provide a formatted JSON response, but customers need an easier way to access this shipping data.
{"name":"shipping","keyspace":"betterbotz","columnDefinitions":[{"Name":"customer_name","TypeDefinition":"text"},{"Name":"id","TypeDefinition":"uuid"},{"Name":"prod_name","TypeDefinition":"text"},{"Name":"city","TypeDefinition":"text"},{"Name":"cust_id","TypeDefinition":"uuid"},{"Name":"country","TypeDefinition":"text"},{"Name":"prod_id","TypeDefinition":"uuid"},{"Name":"state","TypeDefinition":"text"},{"Name":"street","TypeDefinition":"text"},{"Name":"address_id","TypeDefinition":"uuid"},{"Name":"code","TypeDefinition":"text"}],"primaryKey":{"PartitionKey":["prod_name"],"clusteringKey":["customer_name"]},"tableOptions":{"DefaultTimeToLive":null,"clusteringExpression":[{"Column":"customer_name","Order":"asc"}]}}
What about your application in Glitch? Glad you asked! Now that there’s data in your orders table, you can actually see it being returned by your application. Open your Glitch project and complete the following steps:
-
Edit the
sample-run.sh
script to include your Astra database username and password.
ASTRAUSER=username ASTRAPASSWORD=password
Select Tools > Terminal to open a terminal connected to your project.
-
In the terminal, from your home directory (~), run the
./sample-run.sh
script to start the server using your Astra credentials:
cd ~ && ./sample-run.sh
-
With the server running, open a browser and navigate to the following paths to view examples of data retrieval. In each URL, change
your-project-name
to the name of your Glitch project:- This URL verifies that the Express server is running with the included Jade templates: https://your-project-name.glitch.me/
- The
/data
endpoint includes the raw data that is a direct response of the JSON response that is retrieved using the API GET call: https://your-project-name.me/data - The
/datareport
endpoint is a response that includes the data results generated from the Jade template. As configured, customer orders will display at this endpoint: https://your-project-name.glitch.me/datareport
Your data is being returned at the /data
endpoint, and is formatted in a human-readable form at the /datareport
endpoint. You did it! This step is a huge milestone achievement for building an online ordering system for Better Botz.
In the next post, we’ll develop a means to quickly and easily manage CRUD (Create, Read, Update, Delete) operations, which we’ll build with Glitch and Express.js to get data in and out of your tables.
Top comments (2)
In that first PUT example, I think you mean to have "api/rest/v1/keyspaces/test/tables/orders/rows/Otto%20Octavius" in the URL instead of "api/rest/v1/keyspaces/test/tables/tableData/rows/Otto%20Octavius"
Well, my keyspace is called test (so don't worry about that part). But, the part I'm trying to call your attention to is "orders" vs "tableName"