{"id":27370203,"url":"https://github.com/datastaxdevs/workshop-introduction-to-nosql","last_synced_at":"2025-04-13T08:48:18.961Z","repository":{"id":37233314,"uuid":"352545494","full_name":"datastaxdevs/workshop-introduction-to-nosql","owner":"datastaxdevs","description":"Learn NoSQL fundamentals in this hands-on workshop","archived":false,"fork":false,"pushed_at":"2023-01-21T00:00:00.000Z","size":49666,"stargazers_count":267,"open_issues_count":53,"forks_count":199,"subscribers_count":17,"default_branch":"main","last_synced_at":"2023-11-07T17:15:36.187Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/datastaxdevs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-03-29T06:56:23.000Z","updated_at":"2023-10-18T08:20:38.000Z","dependencies_parsed_at":"2023-02-12T07:01:26.713Z","dependency_job_id":null,"html_url":"https://github.com/datastaxdevs/workshop-introduction-to-nosql","commit_stats":null,"previous_names":[],"tags_count":0,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datastaxdevs%2Fworkshop-introduction-to-nosql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datastaxdevs%2Fworkshop-introduction-to-nosql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datastaxdevs%2Fworkshop-introduction-to-nosql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datastaxdevs%2Fworkshop-introduction-to-nosql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/datastaxdevs","download_url":"https://codeload.github.com/datastaxdevs/workshop-introduction-to-nosql/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248688189,"owners_count":21145762,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-04-13T08:48:18.490Z","updated_at":"2025-04-13T08:48:18.948Z","avatar_url":"https://github.com/datastaxdevs.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"## 🎓🔥 Introduction to NoSQL Databases\n\n[![License Apache2](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0)\n[![Discord](https://img.shields.io/discord/685554030159593522)](https://discord.com/widget?id=685554030159593522\u0026theme=dark)\n\n![image](images/intro-to-nosql-cover.png?raw=true)\n\nThese instructions will lead you step by step for the workshop on introducing the NoSQL Databases technologies.\n\n## Materials for the Session\n\nIt 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:\n\n- [Workshop video](#)\n- [Slide deck](./slides.pdf)\n- [Discord chat](https://bit.ly/cassandra-workshop)\n- [Questions and Answers](https://community.datastax.com/)\n\n## Participation Badge / Homework\n\n\u003cimg src=\"images/intro-to-nosql-badge.png?raw=true\" width=\"200\" align=\"right\" /\u003e\n\nTo get the verified badge, you have to complete the following steps:\n\n1. Complete the practice steps of this workshop as explained below. Steps 1-4 (Astra account + tabular/document/key-value databases) are mandatory, step 5 (graph database) is optional. Take a screenshot of completion of the last step for sections 2, 3 and 4 (either a CQL command output or a response in the Swagger UI). _NOTE: When taking screenshots ensure NOT to copy your Astra DB secrets!_\n2. Submit the practice [here](https://dtsx.io/nosql-ws-hw), answering a few \"theory\" questions and also attaching the screenshots.\n\u003c!-- x. Complete [try-it-out scenario](https://www.datastax.com/try-it-out) and make a screenshot of the \"scenario completed\" screen --\u003e\n\n## Practice\n\n1. [Login or Register to AstraDB and create database](#1-login-or-register-to-astradb-and-create-database)\n2. [Tabular Databases](#2-tabular-databases)\n3. [Document Databases](#3-document-databases)\n4. [Key-Value Databases](#4-keyvalue-databases)\n5. [Graph Databases](#5-graph-databases)\n\n## 1. Login or Register to AstraDB and create database\n\n**`ASTRADB`** is the simplest way to run Cassandra with zero operations at all - just push the button and get your cluster. No credit card required,\na monthly free credit to use, covering about 20M reads/writes and 80GB storage (sufficient to run small production workloads), all for FREE.\n\n### ✅ 1a. Register a free account on Astra\n\nClick the button below to login or register on DataStax Astra DB. You can use your `Github`, `Google` accounts or register with an `email`.\n\n\u003ca href=\"https://astra.dev/5-18\"\u003e\u003cimg src=\"https://github.com/datastaxdevs/workshop-graphql-netflix/raw/master/img/create_astra_db.png?raw=true\" /\u003e\u003c/a\u003e\n\n**Use the following values when creating the database** (this makes your life easier further on):\n\n|Field| Value|\n|---|---|\n|**database name**| `workshops` |\n|**keyspace**| `nosql1` |\n|**Cloud Provider**| Stick to GCP and then pick an \"unlocked\" region to start immediately |\n\nMore info on account creation [here](https://awesome-astra.github.io/docs/pages/astra/create-account/).\n\nYou will see your new database as `pending` or `initializing` on the Dashboard.\nThe status will then change to `Active` when the database is ready: this will only take 2-3 minutes.\nAt that point you will also receive a confirmation email.\n\n## 2. Tabular databases\n\nIn a tabular database we will store ... tables! The Astra DB Service is built on Apache Cassandra™, which is tabular. Let's start with this.\n\n\u003e **Tabular databases** organize data in rows and columns, but with a twist from the traditional RDBMS. Also known as wide-column stores or partitioned row stores, they provide the option to organize related rows in partitions that are stored together on the same replicas to allow fast queries. Unlike RDBMSs, the tabular format is not necessarily strict. For example, Apache Cassandra™ does not require all rows to contain values for all columns in the table. Like Key/Value and Document databases, Tabular databases use hashing to retrieve rows from the table. Examples include: Cassandra, HBase, and Google Bigtable.\n\n### ✅ 2a. Describe your Keyspace\n\nAt database creation you provided a keyspace, a logical grouping for tables.\nLet's visualize it.\nIn Astra DB go to CQL Console to enter the following commands\n\n#### Select your db\n\n![image](images/01.png?raw=true)\n\n#### Go to the Cql Console\n![image](images/02.png?raw=true)\n\n#### Enter the describe command\n\n... and press Enter:\n\n```sql\nDESCRIBE KEYSPACES;\n```\n\n![image](images/03.png?raw=true)\n\n### ✅ 2b. Create table\n\n#### Table creation\n\nExecute the following Cassandra Query Language commands\n\n```sql\nUSE nosql1;\n\nCREATE TABLE IF NOT EXISTS accounts_by_user (\n  user_id         UUID,\n  account_id      UUID,\n  account_type    TEXT,\n  account_balance DECIMAL,\n  user_name       TEXT      STATIC,\n  user_email      TEXT      STATIC,\n  PRIMARY KEY ( (user_id), account_id)\n)   WITH CLUSTERING ORDER BY (account_id ASC);\n```\n\n#### Check\n\nCheck keyspace contents and structure:\n\n```sql\nDESCRIBE KEYSPACE nosql1;\n```\n\n_👁️ Expected output_\n\n```\nCREATE KEYSPACE nosql1 WITH replication = {'class': 'NetworkTopologyStrategy', 'eu-central-1': '3'}  AND durable_writes = true;\n\nCREATE TABLE nosql1.accounts_by_user (\n    user_id uuid,\n    account_id uuid,\n    account_balance decimal,\n    account_type text,\n    user_email text static,\n    user_name text static,\n    PRIMARY KEY (user_id, account_id)\n) WITH CLUSTERING ORDER BY (account_id ASC)\n    AND additional_write_policy = '99PERCENTILE'\n    AND bloom_filter_fp_chance = 0.01\n    AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}\n    AND comment = ''\n    AND compaction = {'class': 'org.apache.cassandra.db.compaction.UnifiedCompactionStrategy'}\n    AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}\n    AND crc_check_chance = 1.0\n    AND default_time_to_live = 0\n    AND gc_grace_seconds = 864000\n    AND max_index_interval = 2048\n    AND memtable_flush_period_in_ms = 0\n    AND min_index_interval = 128\n    AND read_repair = 'BLOCKING'\n    AND speculative_retry = '99PERCENTILE';\n```\n\n### ✅ 2c. Working with DATA\n\n#### Insert some entries into the table\n\n```sql\nINSERT INTO accounts_by_user(user_id, account_id, account_balance, account_type, user_email, user_name)\nVALUES(\n    1cafb6a4-396c-4da1-8180-83531b6a41e3,\n    811b56c3-cead-40d9-9a3d-e230dcd64f2f,\n    1500,\n    'Savings',\n    'alice@example.org',\n    'Alice'\n);\n\nINSERT INTO accounts_by_user(user_id, account_id, account_balance, account_type)\nVALUES(\n    1cafb6a4-396c-4da1-8180-83531b6a41e3,\n    83428a85-5c8f-4398-8019-918d6e1d3a93,\n    2500,\n    'Checking'\n);\n\nINSERT INTO accounts_by_user(user_id, account_id, account_balance, account_type, user_email, user_name)\nVALUES(\n    0d2b2319-9c0b-4ecb-8953-98687f6a99ce,\n    81def5e2-84f4-4885-a920-1c14d2be3c20,\n    1000,\n    'Checking',\n    'bob@example.org',\n    'Bob'\n);\n```\n\n#### Read values\n\n```sql\nSELECT * FROM accounts_by_user;\n```\n\n\u003e Such a full-table query is strongly discouraged in most distributed databases\n\u003e as it involves contacting many nodes to assemble the whole result dataset:\n\u003e here we are using it for learning purposes, not in production and on a table\n\u003e with very few rows!\n\n_👁️ Expected output_\n\n```\n user_id                              | account_id                           | user_email        | user_name | account_balance | account_type\n--------------------------------------+--------------------------------------+-------------------+-----------+-----------------+--------------\n 0d2b2319-9c0b-4ecb-8953-98687f6a99ce | 81def5e2-84f4-4885-a920-1c14d2be3c20 |   bob@example.org |       Bob |            1000 |     Checking\n 1cafb6a4-396c-4da1-8180-83531b6a41e3 | 811b56c3-cead-40d9-9a3d-e230dcd64f2f | alice@example.org |     Alice |            1500 |      Savings\n 1cafb6a4-396c-4da1-8180-83531b6a41e3 | 83428a85-5c8f-4398-8019-918d6e1d3a93 | alice@example.org |     Alice |            2500 |     Checking\n\n(3 rows)\n```\n\n\u003e Notice that all three rows are \"filled with data\", despite the second of the insertions above skipping the `user_email` and `user_name` columns:\n\u003e this is because these are **static columns** (i.e. associated to the whole partition) and their value had been written already in the first insertion.\n\n#### Read by primary key\n\n```sql\nSELECT user_email, account_type, account_balance\n  FROM accounts_by_user\n  WHERE user_id=0d2b2319-9c0b-4ecb-8953-98687f6a99ce\n    AND account_id=81def5e2-84f4-4885-a920-1c14d2be3c20;\n```\n\n_👁️ Expected output_\n\n```\n user_email      | account_type | account_balance\n-----------------+--------------+-----------------\n bob@example.org |     Checking |            1000\n\n(1 rows)\n```\n\n### ✅ 2d. Working with PARTITIONS\n\nBut data can be grouped, we stored together what should be retrieved together.\n\n#### Try a query not compatible with the data model\n\n\u003cdetails\u003e\u003csummary\u003e(Optional: click to expand)\u003c/summary\u003e\n\n```\nSELECT account_id, account_type, account_balance\n   FROM accounts_by_user\n   WHERE account_id=81def5e2-84f4-4885-a920-1c14d2be3c20;\n```\n\n\u003c!-- ```\nInvalidRequest: Error from server: code=2200 [Invalid query] message=\"Cannot execute this query as it might involve data filtering and thus may have unpredictable performance. If you want to execute this query despite the performance unpredictability, use ALLOW FILTERING\"\n```\n --\u003e\n\n**`Yes, we know`**, and now let's see why.\n\n```\nTRACING ON;\nSELECT account_id, account_type, account_balance\n   FROM accounts_by_user\n   WHERE account_id=81def5e2-84f4-4885-a920-1c14d2be3c20\n   ALLOW FILTERING;\nTRACING OFF;\n```\n\n\u003e _Note_: `ALLOW FILTERING` is almost never to be used in production, we use it here to see what happens!\n\n_👁️ Output_\n\n```\n account_id                           | account_type | account_balance\n--------------------------------------+--------------+-----------------\n 81def5e2-84f4-4885-a920-1c14d2be3c20 |     Checking |            1000\n\n(1 rows)\n```\n\nBut also (_\"Anatomy of a full-cluster scan\"_):\n\n```\nTracing session: e97b98b0-d146-11ec-a4e5-19251c2b96e1\n\n activity                                                                                                                   | timestamp                  | source      | source_elapsed | client\n----------------------------------------------------------------------------------------------------------------------------+----------------------------+-------------+----------------+-----------------------------------------\n                                                                                                         Execute CQL3 query | 2022-05-11 16:25:03.675000 | 10.0.63.218 |              0 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n Parsing SELECT[....]_by_user\\n   WHERE account_id=81def5e2-84f4-4885-a920-1c14d2be3c20\\n   ALLOW FILTERING; [CoreThread-0] | 2022-05-11 16:25:03.676000 | 10.0.63.218 |            229 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                                                                                         Preparing statement [CoreThread-0] | 2022-05-11 16:25:03.676000 | 10.0.63.218 |            445 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                                                                                Computing ranges to query... [CoreThread-0] | 2022-05-11 16:25:03.681000 | 10.0.63.218 |           5970 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                                                         READS.RANGE_READ message received from /10.0.63.218 [CoreThread-9] | 2022-05-11 16:25:03.682000 | 10.0.31.189 |             -- | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                Submitting range requests on 25 ranges with a concurrency of 1 (0.0 rows per range expected) [CoreThread-0] | 2022-05-11 16:25:03.682000 | 10.0.63.218 |           6197 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                                                                       Submitted 1 concurrent range requests [CoreThread-0] | 2022-05-11 16:25:03.682000 | 10.0.63.218 |           6312 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                                             Sending READS.RANGE_READ message to /10.0.32.75, size=227 bytes [CoreThread-9] | 2022-05-11 16:25:03.682000 | 10.0.63.218 |           6436 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                                            Sending READS.RANGE_READ message to /10.0.31.189, size=227 bytes [CoreThread-8] | 2022-05-11 16:25:03.682000 | 10.0.63.218 |           6436 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                                                         READS.RANGE_READ message received from /10.0.63.218 [CoreThread-4] | 2022-05-11 16:25:03.683000 |  10.0.32.75 |             -- | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n             Executing seq scan across 0 sstables for (min(-9223372036854775808), min(-9223372036854775808)] [CoreThread-4] | 2022-05-11 16:25:03.683000 |  10.0.32.75 |            444 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n             Executing seq scan across 0 sstables for (min(-9223372036854775808), min(-9223372036854775808)] [CoreThread-9] | 2022-05-11 16:25:03.684000 | 10.0.31.189 |            356 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                                                                       Read 1 live rows and 0 tombstone ones [CoreThread-4] | 2022-05-11 16:25:03.684000 |  10.0.32.75 |            789 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                                                                       Read 1 live rows and 0 tombstone ones [CoreThread-9] | 2022-05-11 16:25:03.684000 | 10.0.31.189 |            731 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                                                          Enqueuing READS.RANGE_READ response to /10.0.32.75 [CoreThread-4] | 2022-05-11 16:25:03.684000 |  10.0.32.75 |            897 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                                                         Enqueuing READS.RANGE_READ response to /10.0.31.189 [CoreThread-9] | 2022-05-11 16:25:03.684000 | 10.0.31.189 |            731 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                                            Sending READS.RANGE_READ message to /10.0.63.218, size=212 bytes [CoreThread-7] | 2022-05-11 16:25:03.684000 |  10.0.32.75 |            954 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                                            Sending READS.RANGE_READ message to /10.0.63.218, size=212 bytes [CoreThread-1] | 2022-05-11 16:25:03.684000 | 10.0.31.189 |           1098 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                                                          READS.RANGE_READ message received from /10.0.32.75 [CoreThread-9] | 2022-05-11 16:25:03.685000 | 10.0.63.218 |           9626 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                                                         READS.RANGE_READ message received from /10.0.31.189 [CoreThread-1] | 2022-05-11 16:25:03.702000 | 10.0.63.218 |          27526 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                                                                        Processing response from /10.0.32.75 [CoreThread-0] | 2022-05-11 16:25:03.856000 | 10.0.63.218 |         181075 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                                                                       Processing response from /10.0.31.189 [CoreThread-0] | 2022-05-11 16:25:03.856000 | 10.0.63.218 |         181193 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\nDidn't get enough response rows; actual rows per range: 0.04; remaining rows: 99, new concurrent requests: 1 [CoreThread-0] | 2022-05-11 16:25:03.856000 | 10.0.63.218 |         181384 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n                                                                                                           Request complete | 2022-05-11 16:25:03.856560 | 10.0.63.218 |         181560 | 2898:d2d9:30d9:4a4f:acec:3e3a:3a76:4a7b\n```\n\n\u003c/details\u003e\n\n#### Retrieve data from a whole partition\n\n```sql\nSELECT account_id, account_type, account_balance\n  FROM accounts_by_user\n  WHERE user_id=1cafb6a4-396c-4da1-8180-83531b6a41e3;\n```\n\n_👁️ Expected output_\n\n```\n account_id                           | account_type | account_balance\n--------------------------------------+--------------+-----------------\n 811b56c3-cead-40d9-9a3d-e230dcd64f2f |      Savings |            1500\n 83428a85-5c8f-4398-8019-918d6e1d3a93 |     Checking |            2500\n\n(2 rows)\n```\n\n[🏠 Back to Table of Contents](#table-of-content)\n\n## 3. Document Databases\n\nLet's do some hands-on with document database queries.\n\n\u003e **Document databases** expand on the basic idea of key-value stores where “documents” are more complex, in that they contain data and each document is assigned a unique key, which is used to retrieve the document. These are designed for storing, retrieving, and managing document-oriented information, often stored as JSON. Since the Document database can inspect the document contents, the database can perform some additional retrieval processing. Unlike RDBMSs which require a static schema, Document databases have a flexible schema as defined by the document contents. Examples include: MongoDB and CouchDB. Note that some RDBMS and NoSQL databases outside of pure document stores are able to store and query JSON documents, including Cassandra.\n\n### ✅ 3a. Cassandra native JSON support\n\nIt is not widely known, but Cassandra accepts JSON queries out of the box. You can find more information [here](https://docs.datastax.com/en/cql-oss/3.3/cql/cql_using/useInsertJSON.html).\n\n\u003cdetails\u003e\u003csummary\u003eShow native JSON support\u003c/summary\u003e\n\n#### JSON syntax for insertions\n\nInsert data into Cassandra with JSON syntax:\n\n```sql\nINSERT INTO accounts_by_user JSON '{\n  \"user_id\": \"1cafb6a4-396c-4da1-8180-83531b6a41e3\",\n  \"account_id\": \"811b56c3-cead-40d9-9a3d-e230dcd64f2f\",\n  \"user_email\": \"alice@example.org\",\n  \"user_name\": \"Alice\",\n  \"account_type\": \"Savings\",\n  \"account_balance\": \"8500\"\n}' ;\n```\n\n\u003e Warning: missing fields in the provided JSON will entail explicit insertion of corresponding `null` values.\n\n#### JSON output when querying\n\nIn the same way you can retrieve JSON out of Cassandra ([more info here](https://docs.datastax.com/en/cql-oss/3.3/cql/cql_using/useQueryJSON.html)).\n\n```sql\nSELECT JSON account_type, account_balance\n  FROM accounts_by_user\n  WHERE user_id=1cafb6a4-396c-4da1-8180-83531b6a41e3;\n```\n\n_👁️ Output_\n\n```\n [json]\n-------------------------------------------------------\n  {\"account_type\": \"Savings\", \"account_balance\": 8500}\n {\"account_type\": \"Checking\", \"account_balance\": 2500}\n\n(2 rows)\n```\n\nThis JSON support is but a wrapper around access to the same fixed-schema\ntables seen in the previous section (\"Tabular\").\n\n\u003c/details\u003e\n\n### ✅ 3b. Create a token and open Swagger\n\nWe now turn to using Astra DB's Document API.\n\n#### Token creation\n\nTo do so, first you need to create an Astra DB token, which will\nbe used for authentication to your database.\n\n**Create a token with \"Database Administrator\" privileges following\nthe instructions here: [Create an Astra DB token](https://awesome-astra.github.io/docs/pages/astra/create-token/#c-procedure).**\n(See also [the official docs on tokens](https://docs.datastax.com/en/astra/docs/manage-application-tokens.html).)\n\nKeep the \"token\" ready to use (it is the long string starting with `AstraCS:.....`).\n\n\u003e **⚠️ Important**\n\u003e ```\n\u003e The instructor will show you on screen how to create a token \n\u003e but will have to destroy to token immediately for security reasons.\n\u003e ```\n\n#### Swagger UI\n\nThe Document API can be easily accessed through a Swagger UI:\ngo the \"Connect\" page, stay in the \"Document API\" subpage, and locate the URL under the \"Launching Swagger UI\" heading:\n\n![image](images/connect.png?raw=true)\n\nLocate the \"documents\" section in the Swagger UI. You are now ready to fire requests to the Document API.\n\n![image](images/05.png?raw=true)\n\n### ✅ 3c. Create a new empty collection\n\n![Swagger 3c](images/swagger/swagger_3c.png)\n\n- Access ***Create a new empty collection in a namespace***\n- Click `Try it out` button\n- Fill Header `X-Cassandra-Token` with `\u003cyour_token\u003e`\n- For `namespace-id` use `nosql1`\n- For `body` use \n\n```json\n{ \"name\": \"users\" }\n```\n- Click the `Execute` button\n\nYou will get an `HTTP 201 - Created` return code.\n\n\u003e _Note:_ the response you just got from actually calling the API endpoint\n\u003e is given under the \"Server response\" heading. Do not confuse it with\n\u003e the \"Responses\" found immediately after, which are simply a documentation\n\u003e of all possible response codes (and the return object they quote are static\n\u003e example JSONs).\n\n\u003cdetails\u003e\u003csummary\u003eClick to show a screenshot\u003c/summary\u003e\n  \n![image](images/swagger_responses_annotated.png?raw=true)\n\n\u003c/details\u003e\n\n### ✅ 3d. Create new documents\n\n#### Add a first document\n\n![Swagger 3d](images/swagger/swagger_3d.png)\n\n- Access ***Create a new document***\n- Click `Try it out` button\n- Fill with Header `X-Cassandra-Token` with `AstraCS:...[your_token]...`\n- For `namespace-id` use `nosql1`\n- For `collection-id` use `users`\n- For `body` use \n\n```json\n{\n    \"accounts\": [\n        {\n            \"balance\": \"1000\",\n            \"id\": \"81def5e2-84f4-4885-a920-1c14d2be3c20\",\n            \"type\": \"Checking\"\n        }\n    ],\n    \"email\": \"bob@example.org\",\n    \"id\": \"0d2b2319-9c0b-4ecb-8953-98687f6a99ce\",\n    \"name\": \"Bob\"\n}\n```\n- Click the `Execute` button\n\n_👁️ Expected output (your `documentId` will be different)_\n\n```json\n{\n  \"documentId\": \"137d8609-87f6-4cb7-9506-e52f338e79e9\"\n}\n```\n\n#### Add another document\n\nRepeat with the following body, which has _a different structure_:\n\n```json\n{\n    \"accounts\": [\n        {\n            \"balance\": \"2500\",\n            \"id\": \"83428a85-5c8f-4398-8019-918d6e1d3a93\",\n            \"type\": \"Checking\"\n        },\n        {\n            \"balance\": \"1500\",\n            \"id\": \"811b56c3-cead-40d9-9a3d-e230dcd64f2f\",\n            \"type\": \"Savings\"\n        }\n    ],\n    \"email\": \"alice@example.org\",\n    \"id\": \"1cafb6a4-396c-4da1-8180-83531b6a41e3\",\n    \"name\": \"Alice\"\n}\n```\n\nAs before, the document will automatically be given an internal unique `documentId`.\n\n\n### ✅ 3e. Retrieve a document by its ID\n\n![Swagger 3e](images/swagger/swagger_3eB.png)\n\n- Access ***Get a document***\n- Click `Try it out` button\n- Fill Header `X-Cassandra-Token` with `\u003cyour_token\u003e`\n- For `namespace-id` use `nosql1`\n- For `collection-id` use `users`\n- For `document-id` use Bob's `documentId` (e.g. `137d8609-87f6-4cb7-9506-e52f338e79e9` in the above sample output)\n- Click the `Execute` button\n\n_👁️ Expected output_\n\n```json\n{\n  \"documentId\": \"137d8609-87f6-4cb7-9506-e52f338e79e9\",\n  \"data\": {\n    \"accounts\": [\n      {\n        \"balance\": \"1000\",\n        \"id\": \"81def5e2-84f4-4885-a920-1c14d2be3c20\",\n        \"type\": \"Checking\"\n      }\n    ],\n    \"email\": \"bob@example.org\",\n    \"id\": \"0d2b2319-9c0b-4ecb-8953-98687f6a99ce\",\n    \"name\": \"Bob\"\n  }\n}\n```\n\n\n### ✅ 3f. Find all documents in a collection\n\n![Swagger 3f](images/swagger/swagger_3fB.png)\n\n- Access ***Search documents in a collection***\n- Click `Try it out` button\n- Fill Header `X-Cassandra-Token` with `\u003cyour_token\u003e`\n- For `namespace-id` use `nosql1`\n- For `collection-id` use `users`\n\nLeave other fields blank (in particular, every query is paged in Cassandra).\n\n- Click the `Execute` button\n\n_👁️ Expected output (take note of the `documentId`s of your output for later)_\n\n```json\n{\n  \"data\": {\n    \"6d0aafd9-3c2c-461f-92c6-08322eaef5da\": {\n      \"accounts\": [\n        {\n          \"balance\": \"2500\",\n          \"id\": \"83428a85-5c8f-4398-8019-918d6e1d3a93\",\n          \"type\": \"Checking\"\n        },\n        {\n          \"balance\": \"1500\",\n          \"id\": \"811b56c3-cead-40d9-9a3d-e230dcd64f2f\",\n          \"type\": \"Savings\"\n        }\n      ],\n      \"email\": \"alice@example.org\",\n      \"id\": \"1cafb6a4-396c-4da1-8180-83531b6a41e3\",\n      \"name\": \"Alice\"\n    },\n    \"137d8609-87f6-4cb7-9506-e52f338e79e9\": {\n      \"accounts\": [\n        {\n          \"balance\": \"1000\",\n          \"id\": \"81def5e2-84f4-4885-a920-1c14d2be3c20\",\n          \"type\": \"Checking\"\n        }\n      ],\n      \"email\": \"bob@example.org\",\n      \"id\": \"0d2b2319-9c0b-4ecb-8953-98687f6a99ce\",\n      \"name\": \"Bob\"\n    }\n  }\n}\n```\n\n\n### ✅ 3g. Search document with a \"where\" clause\n\nThe endpoint you just used can support [`where` clauses](https://docs.datastax.com/en/astra/docs/read-documents.html#_retrieving_a_document_using_a_where_clause) as well,\nexpressed as JSON. You don't need to navigate away from it do try the\nfollowing:\n\n![Swagger 3g](images/swagger/swagger_3g.png)\n\n- Access ***Search documents in a collection*** (you should be there already)\n- Click `Try it out` button\n- Fill Header `X-Cassandra-Token` with `\u003cyour_token\u003e`\n- For `namespace-id` use `nosql1`\n- For `collection-id` use `users`\n- For `where` use `{\"name\": {\"$eq\": \"Alice\"}}`\n- Click the `Execute` button\n\n*👁️ Expected output*\n\n```json\n{\n  \"data\": {\n    \"6d0aafd9-3c2c-461f-92c6-08322eaef5da\": {\n      \"accounts\": [\n        {\n          \"balance\": \"2500\",\n          \"id\": \"83428a85-5c8f-4398-8019-918d6e1d3a93\",\n          \"type\": \"Checking\"\n        },\n        {\n          \"balance\": \"1500\",\n          \"id\": \"811b56c3-cead-40d9-9a3d-e230dcd64f2f\",\n          \"type\": \"Savings\"\n        }\n      ],\n      \"email\": \"alice@example.org\",\n      \"id\": \"1cafb6a4-396c-4da1-8180-83531b6a41e3\",\n      \"name\": \"Alice\"\n    }\n  }\n}\n```\n\n[🏠 Back to Table of Contents](#table-of-content)\n\n## 4. Key/Value Databases\n\n\u003e **Key/Value databases** are some of the simplest and yet powerful as all of the data within consists of an indexed key and a value. Key-value databases use a hashing mechanism, so that that given a key, the database can quickly retrieve the associated value. Hashing mechanisms provide constant time access, which means they maintain high performance even at large scale. The keys can be any type of object, but are typically a string. The values are generally opaque blobs (i.e. a sequence of bytes that the database does not interpret). Examples include: Redis, Amazon DynamoDB, Riak, and Oracle NoSQL database. Some tabular NoSQL databases, like Cassandra, can also service key/value needs.\n\n### ✅ 4a. Create a table for Key/Value\n\nGo to the CQL Console again and issue the following commands\nto create a new, simple table with just two columns:\n\n```sql\nUSE nosql1;\n\nCREATE TABLE users_kv (\n  key   TEXT PRIMARY KEY,\n  value TEXT\n);\n```\n\n### ✅ 4b. Populate the table\n\nInsert into the table all the following entries.\nNote that all inserted values, regardless of their \"true\" data type,\nhave been coerced into strings according to the table schema.\nAlso note how the keys are structured and how some entries reference other,\neffectively creating a set of interconnected pieces of information on the users:\n\n```sql\nINSERT INTO users_kv (key, value) VALUES ('user:1cafb6a4-396c-4da1-8180-83531b6a41e3:name',       'Alice');\nINSERT INTO users_kv (key, value) VALUES ('user:1cafb6a4-396c-4da1-8180-83531b6a41e3:email',      'alice@example.org');\nINSERT INTO users_kv (key, value) VALUES ('user:1cafb6a4-396c-4da1-8180-83531b6a41e3:accounts',   '{83428a85-5c8f-4398-8019-918d6e1d3a93, 811b56c3-cead-40d9-9a3d-e230dcd64f2f}');\n\nINSERT INTO users_kv (key, value) VALUES ('user:0d2b2319-9c0b-4ecb-8953-98687f6a99ce:name',       'Bob');\nINSERT INTO users_kv (key, value) VALUES ('user:0d2b2319-9c0b-4ecb-8953-98687f6a99ce:email',      'bob@example.org');\nINSERT INTO users_kv (key, value) VALUES ('user:0d2b2319-9c0b-4ecb-8953-98687f6a99ce:accounts',   '{81def5e2-84f4-4885-a920-1c14d2be3c20}');\n\nINSERT INTO users_kv (key, value) VALUES ('account:83428a85-5c8f-4398-8019-918d6e1d3a93:type',    'Checking');\nINSERT INTO users_kv (key, value) VALUES ('account:83428a85-5c8f-4398-8019-918d6e1d3a93:balance', '2500');\n\nINSERT INTO users_kv (key, value) VALUES ('account:811b56c3-cead-40d9-9a3d-e230dcd64f2f:type',    'Savings');\nINSERT INTO users_kv (key, value) VALUES ('account:811b56c3-cead-40d9-9a3d-e230dcd64f2f:balance', '1500');\n\nINSERT INTO users_kv (key, value) VALUES ('account:81def5e2-84f4-4885-a920-1c14d2be3c20:type',    'Checking');\nINSERT INTO users_kv (key, value) VALUES ('account:81def5e2-84f4-4885-a920-1c14d2be3c20:balance', '1000');\n```\n\n### ✅ 4c. Update a value\n\nYou can imagine an application \"navigating the keys\" (e.g, from an user to an account) for instance\nwhen it must update a balance. The actual update would look like:\n\n```sql\nINSERT INTO users_kv (key, value) VALUES ('account:81def5e2-84f4-4885-a920-1c14d2be3c20:balance', '9000');\n```\n\nLet's check:\n\n```sql\nSELECT * FROM users_kv WHERE key = 'account:81def5e2-84f4-4885-a920-1c14d2be3c20:balance';\n```\n\n*👁️ Expected output*\n\n```\n key                                                  | value\n------------------------------------------------------+-------\n account:81def5e2-84f4-4885-a920-1c14d2be3c20:balance |  9000\n\n(1 rows)\n```\n\n#### Alternative update syntax\n\nThe same result is obtained with\n\n```sql\nUPDATE users_kv SET value = '-500' WHERE key = 'account:81def5e2-84f4-4885-a920-1c14d2be3c20:balance';\n```\n\nindeed, in most key-value data stores, inserting and updating are one and the same operation\nsince the main goal is usually the highest performance (hence, row-existence checks are skipped altogether).\n\nThus, writing entries with the key of a pre-existing entry will simply overwrite the less recent values,\nenabling a very efficient and simple deduplication strategy.\n\nCheck once more what's in the table:\n\n```sql\nSELECT * FROM users_kv ;\n```\n\n*👁️ Expected output*\n\n\n```\n key                                                  | value\n------------------------------------------------------+------------------------------------------------------------------------------\n account:81def5e2-84f4-4885-a920-1c14d2be3c20:balance |                                                                         -500\n   user:0d2b2319-9c0b-4ecb-8953-98687f6a99ce:accounts |                                       {81def5e2-84f4-4885-a920-1c14d2be3c20}\n account:811b56c3-cead-40d9-9a3d-e230dcd64f2f:balance |                                                                         1500\n   user:1cafb6a4-396c-4da1-8180-83531b6a41e3:accounts | {83428a85-5c8f-4398-8019-918d6e1d3a93, 811b56c3-cead-40d9-9a3d-e230dcd64f2f}\n      user:1cafb6a4-396c-4da1-8180-83531b6a41e3:email |                                                            alice@example.org\n       user:1cafb6a4-396c-4da1-8180-83531b6a41e3:name |                                                                        Alice\n       user:0d2b2319-9c0b-4ecb-8953-98687f6a99ce:name |                                                                          Bob\n      user:0d2b2319-9c0b-4ecb-8953-98687f6a99ce:email |                                                              bob@example.org\n    account:83428a85-5c8f-4398-8019-918d6e1d3a93:type |                                                                     Checking\n    account:811b56c3-cead-40d9-9a3d-e230dcd64f2f:type |                                                                      Savings\n    account:81def5e2-84f4-4885-a920-1c14d2be3c20:type |                                                                     Checking\n account:83428a85-5c8f-4398-8019-918d6e1d3a93:balance |                                                                         2500\n\n(12 rows)\n```\n\n[🏠 Back to Table of Contents](#table-of-content)\n\n## 5. Graph Databases\n\n\u003e **Graph databases** store their data using a graph metaphor to exploit the relationships between data. Nodes in the graph represent data items, and edges represent the relationships between the data items. Graph databases are designed for highly complex and connected data, which outpaces the relationship and JOIN capabilities of an RDBMS. Graph databases are often exceptionally good at finding commonalities and anomalies among large data sets. Examples of Graph databases include DataStax Graph, Neo4J, JanusGraph, and Amazon Neptune.\n\nAstra DB does not contain yet a way to implement Graph Databases use cases. But at Datastax we do have a product called [DataStax Graph](https://www.datastax.com/products/datastax-graph) that you can use for free when not in production.\n\nFor graph databases, the presenter will show a demo based on the example in the slides.\n\nThe hands-on practice for you is different. But since it cannot be done in the browser using\nAstra DB like the rest, it is kept separate and not included in today's curriculum.\n\n🔥 Yet, you are strongly encouraged to try it at your own pace, on your own computer,\nby following the instructions given here: [Graph Databases Practice](graph_databases.md). 🔥\n\n\u003e Try it out, it's super cool!\n\n## THE END\n\nCongratulations! You made it to the END.\n\nSee you next time!\n\n[🏠 Back to Table of Contents](#table-of-content)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatastaxdevs%2Fworkshop-introduction-to-nosql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdatastaxdevs%2Fworkshop-introduction-to-nosql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatastaxdevs%2Fworkshop-introduction-to-nosql/lists"}