Loading repository data…
Loading repository data…
datastaxdevs / repository
Are you building or do you support an e-commerce website? If so, then this content is for you! Worldwide digital sales in 2020 eclipsed four trillion dollars (USD). Businesses that want to compete, need a high performing e-commerce website. Here, we will demonstrate how to build a high performing persistence layer with DataStax ASTRA DB.
It doesn't matter if you join our workshop live or you prefer to do at your own pace, we have you covered. In this repository, you'll find everything you need for this workshop:
If you cannot attend this workshop live, recordings of this workshop and many more is available on Youtube.
Complete the homework to earn the badge for this workshop (awarded only at the end of the series).
Are you building or do you support an e-commerce website? If so, then this content is for you!
Worldwide digital sales in 2020 eclipsed four trillion dollars (USD). Businesses that want to compete, need a high performing e-commerce website. Here, we will demonstrate how to build a high performing persistence layer with DataStax ASTRA DB.
Why does an e-commerce site need to be fast? Because most consumers will leave a web page or a mobile app if it takes longer than a few seconds to load. In the content below, we will cover how to build high-performing data models and services, helping you to build a e-commerce site with high throughput and low latency.
You can skip to step 2c if you have already created a keyspace ecommerce in database demos. Otherwise (if you did not attend the previous installment of the e-commerce worksop):
ASTRA DB is the simplest way to run Cassandra with zero operations - just push the button and get your cluster. No credit card required, $25.00 USD credit every month, roughly 20M read/write operations, 80GB storage monthly - sufficient to run small production workloads.
If you do not have an account yet, register and sign in to Astra DB: This is FREE and NO CREDIT CARD is required. https://astra.datastax.com: You can use your Github, Google accounts or register with an email.
Make sure to chose a password with minimum 8 characters, containing upper and lowercase letters, at least one number and special character
Follow this guide, to set up a pay as you go database with a free $25 monthly credit. You will find below recommended values to enter:
For the database name - demos
For the keyspace name - ecommerce
You can technically use whatever name(s) you want and update the code to reflect the keyspace. This is really to get you on a happy path for the first run.
For provider and region: For Astra DB, select GCP as a provider and then the related region is where your database will reside physically (choose one close to you or your users).
Create the database. Review all the fields to make sure they are as shown, and click the Create Database button.
👁️ Walkthrough
The Walkthrough mentions a different keyspace, make sure to use ecommerce
You will see your new database pending in the Dashboard.
To connect to the database programmatically, you need to make sure the status will change to Active. This happens when the database is ready, and will only take 2-3 minutes. You will also receive an email when it is ready.
👁️ Expected Output
If it's in a standby state you can hit Connect and CQL Console on top.
You should see a message something like below.
👁️ Expected Output
{"message":"Resuming your database, please try again shortly."}
Here we will walk through how to create an Astra Streaming Tenant. Start by clicking the "Create Stream" button in the left navigation pane.
On the next page, provide a name for your tenant and select a provider/region. Click the blue "Create Tenant" button when complete.
Note that Tenant Names must be unique across providers. To ensure uniqueness, name it "ecommerce-" followed by your name or company.
Now we need to create topics within our tenant. Click on the link or on the "Topics" tab. You should see the "default" namespace with an "Add Topic" button (on the right). Click the "Add Topic" button.
Name the topic "pending-orders" and make sure that the "Persistent" switch is selected. Don't worry about the "Partitioned" switch for now. Click the "Add Topic" button when ready.
Repeat this process to add 3 more topics:
When you are done, your "Topics" tab should look similar to this:
Introduction This section will provide DDL to create three tables inside the "ecommerce" keyspace: category, price, and product.
The product table supports all product data queries, and uses product_id as a single key. It has a few columns for specific product data, but any ad-hoc or non-standard properties can be added to the specifications map.
The category table will support all product navigation service calls. It is designed to provide recursive, hierarchical navigation without a pre-set limit on the number of levels. The top-most level only exists as a parent_id, and the bottom-most level contains products.
The price table was intentionally split-off from product. There are several reasons for this. Price data is much more likely to change than pure product data (different read/write patterns). Also, large enterprises typically have separate teams for product and price, meaning they will usually have different micro-service layers and data stores.
The featured_product_groups table was a late-add, to be able to provide some extra "atmosphere" of an e-commerce website. This way, the UI has a means by which to highlight a few, select products.
The user_carts table supports cart metadata. Carts are not expected to be long-lived, so they have a default TTL (time to live) of 60 days (5,184,000 seconds). Carts also have a name as a part of the key, so that the user can have multiple carts (think "wish lists").
The cart_products table holds data on the products added to the cart. The cart uses product_timestamp as the first clustering key in descending order; this way products in the cart will be listed with the most-recently-added products at the top. Like user_carts, each entry has a 60 day TTL.
The user table holds all data on the user, keyed by a single PRIMARY KEY on user_id. It's main features contain TEXT (string) data for common user properties, as well as a collection of addresses. This is because users (especially B-to-B) may have multiple addresses (mail-to, ship-to, bill-to, etc). The addresses collection is built on a special user defined type (UDT) and FROZEN to treat the collection as a Binary Large OBject (BLOB) to reduce tombstones (required by CQL).
As mentioned above, the address UDT contains properties used for postal contacts. All properties are of the TEXT datatype.
The user_by_email table is intended to be used as a "manual index" on email address. Essentially, it is a lookup table returning the user_id associated with an email address. This is necessary as user_email is nigh-unique (in terms of cardinality of values), and thus a CQL secondary index would perform quite poorly.
The order_by_id table holds detail on each order. It partitions on order_id for optimal data distribution, and clusters on product_name and product_id for sort order. The columns specific to the order itself (and not a product) are STATIC so that they are only stored once (with the partition key).
The order_by_user table holds a reference to each order by user_id. The idea, is that this table is queried by user_id and the results are shown on an "order history" page for that user. Then, each order can be clicked-on, revealing the detail contained in the order_by_id table. order_id is a TimeUUID (version 1 UUID) type, which is converted into a human-readable timestamp in the service layer.
The order_status_history table maintains a history of each status for an order. It is meant to be used with queries to the order_by_id table, so that a user may see the status progression of their order.
use ecommerce;
/* Session 1 - Product data model */
/* category table */
CREATE TABLE IF NOT EXISTS category (
parent_id UUID,
category_id UUID,
name TEXT,
image TEXT,
products LIST<TEXT>,
PRIMARY KEY (parent_id,category_id));
/* price table */
CREATE TABLE IF NOT EXISTS price (
product_id TEXT,
store_id TEXT,
value DECIMAL,
PRIMARY KEY(product_id,store_id));
/* product table */
CREATE TABLE IF NOT EXISTS product (
product_id TEXT,
product_group TEXT,
name TEXT,
brand TEXT,
model_number TEXT,
short_desc TEXT,
long_desc TEXT,
specifications MAP<TEXT,TEXT>,
linked_documents MAP<TEXT,TEXT>,
images SET<TEXT>,
PRIMARY KEY(product_id));
/* featured product groups table */
CREATE TABLE IF NOT EXISTS featured_product_groups (
feature_id INT,
category_id UUID,
name TEXT,
image TEXT,
parent_id UUID,
price DECIMAL,
PRIMARY KEY (feature_id,category_id));
/* Session 2 - Shopping Cart data model */
CREATE TABLE IF NOT EXISTS user_carts (
user_id uuid,
cart_name text,
cart_id uuid,
cart_is_active boolean,
user_email text,
PRIMARY KEY (user_id, cart_name, cart_id)
) WITH default_time_to_live = 5184000;
CREATE TABLE IF NOT EXISTS cart_products (
cart_id uuid,
product_timestamp timestamp,
product_id text,
product_description text,
product_name text,
quantity in