├── .DS_Store ├── LICENSE ├── README.md ├── astra.json ├── images ├── badge_data_modeling.png ├── create_astra_db_button.png ├── illustrations.png ├── kdm_01.png ├── kdm_02.png ├── kdm_03.png ├── killrcoda_01.png ├── killrcoda_02.png └── splash.png ├── materials ├── kdm_sensor_data.xml └── kdm_sensor_data_2.xml └── slides └── slides.pdf /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/workshop-cassandra-data-modeling/d7a1422b262e044512e85b0daea0fcd9f4e19652/.DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🎓🎓 Apache Cassandra® Data Modelling 2 | 3 | Welcome to the **Apache Cassandra® Data Modelling** workshop! In this two-hour workshop, we show the methodology to build an effective data model with the distributed `NoSQL database Apache Cassandra™`. 4 | 5 | Using **Astra DB**, the cloud based _Cassandra-as-a-Service_ platform delivered by DataStax, we will cover the process for every developer who wants to build an application: list the use cases and build an effective data model. 6 | 7 | ![](images/splash.png) 8 | 9 | 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: 10 | 11 | > [🔖 Accessing HANDS-ON](#-start-hands-on) 12 | 13 | ## 📋 Table of content 14 | 15 | 16 | 17 | 1. [Objectives](#1-objectives) 18 | 2. [Frequently Asked Questions](#2-frequently-asked-questions) 19 | 3. [Materials for the Session](#3-materials-for-the-session) 20 | 4. [Create Your Astra DB Instance](#4-create-your-astra-db-instance) 21 | 5. [Tables with Single-Row and Multi-Row Partitions](#5-tables-with-single-row-and-multi-row-partitions) 22 | 6. [Dynamic Bucketing](#6-dynamic-bucketing) 23 | 7. [Working with Data Types](#7-working-with-data-types) 24 | 8. [KDM Data Modeling Tool](#8-kdm-data-modeling-tool) 25 | 9. [Sensor Data Modeling](#9-sensor-data-modeling) 26 | 10. [Homework](#10-homework) 27 | 11. [What's NEXT ](#11-whats-next-) 28 |


29 | 30 | ## 1. Objectives 31 | 32 | 1️⃣ **Understand how data is distributed and organized in Apache Cassandra®** 33 | 34 | 2️⃣ **Learn how primary, partition, and clustering keys are defined in Apache Cassandra®** 35 | 36 | 3️⃣ **Become familiar with CQL data types in Apache Cassandra®** 37 | 38 | 4️⃣ **Learn about the data modeling methodology for Apache Cassandra®** 39 | 40 | 🚀 **Have fun with an interactive session** 41 | 42 | ## 2. Frequently Asked Questions 43 | 44 |

45 |

46 | 1️⃣ Can I run this workshop on my computer? 47 |
48 |

There is nothing preventing you from running the workshop on your own machine. If you do so, you will need the following: 49 |

    50 |
  1. git installed on your local system 51 |
52 |

53 | In this readme, we try to provide instructions for local development as well - but keep in mind that the main focus is development on Gitpod, hence we can't guarantee live support about local development in order to keep on track with the schedule. However, we will do our best to give you the info you need to succeed. 54 |
55 |

56 |

57 | 2️⃣ What other prerequisites are required? 58 |
59 | 64 |

65 |
66 |

67 |

68 | 3️⃣ Do I need to pay for anything for this workshop? 69 |
70 | No. All tools and services we provide here are FREE. FREE not only during the session but also after. 71 |
72 |

73 |

74 | 4️⃣ Will I get a certificate if I attend this workshop? 75 |
76 | Attending the session is not enough. You need to complete the homework detailed below and you will get a nice badge that you can share on LinkedIn or anywhere else. 77 |
78 |

79 | 80 | ## 3. Materials for the Session 81 | 82 | It doesn't matter if you join our workshop live or you prefer to work at your own pace, 83 | we have you covered. In this repository, you'll find everything you need for this workshop: 84 | 85 | - [Slide deck](/slides/slides.pdf) 86 | - [Discord chat](https://dtsx.io/discord) 87 | - [Questions and Answers](https://community.datastax.com/) 88 | 89 | ---- 90 | 91 | # 🏁 Start Hands-on 92 | 93 | ## 4. Create Your Astra DB Instance 94 | 95 | _**`ASTRA DB`** is the simplest way to run Cassandra with zero operations at all - just push the button and get your cluster. No credit card required, 40M read/write operations and about 80GB storage monthly for free - sufficient to run small production workloads. If you end your credits the databases will pause, no charge_ 96 | 97 | Leveraging [Database creation guide](https://awesome-astra.github.io/docs/pages/astra/create-instance/#c-procedure) create a database. *Right-Click the button* with *Open in a new TAB.* 98 | 99 | 100 | 101 | |Field|Value| 102 | |---|---| 103 | |**Database Name**| `workshops`| 104 | |**Keyspace Name**| `sensor_data`| 105 | |**Regions**| Select `GOOGLE CLOUD`, then an Area close to you, then a region with no LOCKER 🔒 icons, those are the region you can use for free. | 106 | 107 | > **ℹ️ Note:** If you already have a database `workshops`, simply add a keyspace `sensor_data` using the `Add Keyspace` button on the bottom right hand corner of db dashboard page. 108 | 109 | While the database is being created, you will also get a **Security token**: 110 | save it somewhere safe, as it will be needed to later in other workshops (In particular the string starting with `AstraCS:...`.) 111 | 112 | > **⚠️ Important** 113 | > ``` 114 | > The instructor will show you on screen how to create a token 115 | > but will have to destroy to token immediately for security reasons. 116 | > ``` 117 | 118 | The status will change from `Pending` to `Active` when the database is ready, this will only take 2-3 minutes. You will also receive an email when it is ready. 119 | 120 | [🏠 Back to Table of Contents](#-table-of-content) 121 | 122 | ## 5. Tables with Single-Row and Multi-Row Partitions 123 | 124 | A [GitHub](https://github.com) account may be required to run this hands-on lab in Gitpod. 125 | 126 | ### ✅ Part 1: [Tables with Single-Row Partitions](https://gitpod.io/#https://github.com/DataStax-Academy/workshop-cassandra-data-modeling-tables-single-row-partitions/) 127 | 128 | ### ✅ Part 2: [Tables with Multi-Row Partitions](https://gitpod.io/#https://github.com/DataStax-Academy/workshop-cassandra-data-modeling-tables-multi-row-partitions/) 129 | 130 | [🏠 Back to Table of Contents](#-table-of-content) 131 | 132 | ## 6. Dynamic Bucketing 133 | 134 |

135 |

📌 Homework 1

136 | 137 | Consider the table that supports query `Find all sensors in a specified network`: 138 | ```sql 139 | CREATE TABLE sensors_by_network_2 ( 140 | network TEXT, 141 | sensor TEXT, 142 | PRIMARY KEY ((network), sensor) 143 | ); 144 | ``` 145 | 146 | Assume that a network may have none to millions of sensors. With dynamic bucketing, we can introduce artificial buckets to store sensors. A network with a few sensors may only need one bucket. A network with many sensors may need many buckets. Once buckets belonging to a particular network get filled with sensors, we can dynamically assign new buckets to store new sensors of this network. 147 | 148 | 📘 **Implement dynamic bucketing in Astra DB** 149 | ```sql 150 | -- Table to manage buckets 151 | CREATE TABLE buckets_by_network ( 152 | network TEXT, 153 | bucket TIMEUUID, 154 | PRIMARY KEY ((network), bucket) 155 | ) WITH CLUSTERING ORDER BY (bucket DESC); 156 | 157 | -- Table to store sensors 158 | CREATE TABLE sensors_by_bucket ( 159 | bucket TIMEUUID, 160 | sensor TEXT, 161 | PRIMARY KEY ((bucket), sensor) 162 | ); 163 | 164 | 165 | -- Sample data 166 | INSERT INTO buckets_by_network (network, bucket) VALUES ('forest-net', 49171ffe-0d12-11ed-861d-0242ac120002); 167 | INSERT INTO buckets_by_network (network, bucket) VALUES ('forest-net', 74a13ede-0d12-11ed-861d-0242ac120002); 168 | 169 | INSERT INTO sensors_by_bucket (bucket, sensor) VALUES (49171ffe-0d12-11ed-861d-0242ac120002, 's1001'); 170 | INSERT INTO sensors_by_bucket (bucket, sensor) VALUES (49171ffe-0d12-11ed-861d-0242ac120002, 's1002'); 171 | 172 | INSERT INTO sensors_by_bucket (bucket, sensor) VALUES (74a13ede-0d12-11ed-861d-0242ac120002, 's1003'); 173 | ``` 174 | 175 | 📘 **Add a new sensor to a network** 176 | 177 | 1. Get the latest bucket. 178 | ```sql 179 | SELECT bucket FROM buckets_by_network WHERE network = 'forest-net' LIMIT 1; 180 | ``` 181 | 182 | 2. Check the number of sensors in the bucket. 183 | ```sql 184 | SELECT COUNT(*) AS sensors 185 | FROM sensors_by_bucket WHERE bucket = 74a13ede-0d12-11ed-861d-0242ac120002; 186 | ``` 187 | 188 | 3. Depending on the sensors-per-bucket threshold, insert a new sensor into the existing bucket, or create a new bucket and insert into the new bucket. 189 | ```sql 190 | INSERT INTO sensors_by_bucket (bucket, sensor) VALUES (74a13ede-0d12-11ed-861d-0242ac120002, 's1004'); 191 | ``` 192 | 193 | 📘 **Retrieve sensors in a specified network** 194 | 195 | 1. Retrieve the buckets 196 | ```sql 197 | SELECT bucket FROM buckets_by_network WHERE network = 'forest-net'; 198 | ``` 199 | 200 | 2. Retrieve the sensors 201 | ```sql 202 | SELECT sensor 203 | FROM sensors_by_bucket 204 | WHERE bucket IN (74a13ede-0d12-11ed-861d-0242ac120002, 49171ffe-0d12-11ed-861d-0242ac120002); 205 | ``` 206 | 207 |
208 | 209 | [🏠 Back to Table of Contents](#-table-of-content) 210 | 211 | ## 7. Working with Data Types 212 | 213 |
214 |

📌 Homework 2

215 | 216 | ### ✅ Step 7a. `List` Collections 217 | 218 | 📘 **Command to execute** 219 | 220 | ```sql 221 | // Definition 222 | CREATE TABLE IF NOT EXISTS table_with_list ( 223 | uid uuid, 224 | items list, 225 | PRIMARY KEY (uid) 226 | ); 227 | 228 | // Insert 229 | INSERT INTO table_with_list(uid,items) 230 | VALUES (c7133017-6409-4d7a-9479-07a5c1e79306, ['a', 'b', 'c']); 231 | 232 | // Replace 233 | UPDATE table_with_list SET items = ['d', 'e'] 234 | WHERE uid = c7133017-6409-4d7a-9479-07a5c1e79306; 235 | 236 | // Show result 237 | SELECT * FROM table_with_list ; 238 | 239 | // Append to list 240 | UPDATE table_with_list SET items = items + ['f'] 241 | WHERE uid = c7133017-6409-4d7a-9479-07a5c1e79306; 242 | 243 | // Replace an element (not available in Astra because read before write) 244 | UPDATE table_with_list SET items[0] = ['g'] 245 | WHERE uid = c7133017-6409-4d7a-9479-07a5c1e79306; 246 | ``` 247 | 248 | ### ✅ Step 7b. `Set` Collections 249 | 250 | 📘 **Command to execute** 251 | 252 | ```sql 253 | // Definition 254 | CREATE TABLE IF NOT EXISTS table_with_set ( 255 | uid uuid, 256 | animals set, 257 | PRIMARY KEY (uid) 258 | ); 259 | 260 | // Insert 261 | INSERT INTO table_with_set(uid,animals) 262 | VALUES (87fad746-4adf-4107-9858-df8643564186, {'spider', 'cat', 'dog'}); 263 | 264 | // Replace 265 | UPDATE table_with_set SET animals = {'pangolin', 'bat'} 266 | WHERE uid = 87fad746-4adf-4107-9858-df8643564186; 267 | 268 | // Show result 269 | SELECT * FROM table_with_set; 270 | 271 | // Append to Set 272 | UPDATE table_with_set SET animals = animals + {'sheep'} 273 | WHERE uid = 87fad746-4adf-4107-9858-df8643564186; 274 | ``` 275 | 276 | ### ✅ Step 7c. `Map` Collections 277 | 278 | 📘 **Command to execute** 279 | 280 | 281 | ```sql 282 | // Definition 283 | CREATE TABLE IF NOT EXISTS table_with_map ( 284 | uid text, 285 | dictionary map, 286 | PRIMARY KEY (uid) 287 | ); 288 | 289 | // Insert 290 | INSERT INTO table_with_map(uid, dictionary) 291 | VALUES ('fr_en', {'fromage':'cheese', 'vin':'wine', 'pain':'bread'}); 292 | 293 | // Replace 294 | UPDATE table_with_map SET dictionary = {'saucisse': 'sausage'} 295 | WHERE uid = 'fr_en'; 296 | 297 | // Show result 298 | SELECT * FROM table_with_map; 299 | 300 | // Append to Map 301 | UPDATE table_with_map SET dictionary = dictionary + {'frites':'fries'} 302 | WHERE uid = 'fr_en'; 303 | ``` 304 | 305 | ### ✅ Step 7d. User-Defined Types 306 | 307 | 📘 **Command to execute** 308 | 309 | ```sql 310 | // Definition 311 | CREATE TYPE IF NOT EXISTS udt_address ( 312 | street text, 313 | city text, 314 | state text, 315 | ); 316 | 317 | // Use the UDT in a table 318 | CREATE TABLE IF NOT EXISTS table_with_udt ( 319 | uid text, 320 | address udt_address, 321 | PRIMARY KEY (uid) 322 | ); 323 | 324 | // INSERT (not quote on field names like street) 325 | INSERT INTO table_with_udt(uid, address) 326 | VALUES ('superman', {street:'daily planet',city:'metropolis',state:'CA'}); 327 | 328 | // Replace 329 | UPDATE table_with_udt 330 | SET address = {street:'pingouin alley',city:'antarctica',state:'melting'} 331 | WHERE uid = 'superman'; 332 | 333 | // Replace a single field 334 | UPDATE table_with_udt 335 | SET address.state = 'melt' 336 | WHERE uid = 'superman'; 337 | ``` 338 | 339 | ### ✅ Step 7e. Counters 340 | 341 | 📘 **Command to execute** 342 | 343 | ```sql 344 | // Definition 345 | CREATE TABLE IF NOT EXISTS table_with_counters ( 346 | handle text, 347 | following counter, 348 | followers counter, 349 | notifications counter, 350 | PRIMARY KEY (handle) 351 | ); 352 | 353 | // You have a new follower 354 | UPDATE table_with_counters SET followers = followers + 1 355 | WHERE handle = 'clunven'; 356 | 357 | // Some counters are... null 358 | SELECT * from table_with_counters; 359 | 360 | // Set to 0... but set is not valid 361 | UPDATE table_with_counters 362 | SET following = following + 0, notifications = notifications + 0 363 | WHERE handle = 'clunven'; 364 | 365 | // Following someone 366 | UPDATE table_with_counters SET following = following + 1 367 | WHERE handle = 'clunven'; 368 | 369 | // You have a new message 370 | UPDATE table_with_counters SET notifications = notifications + 1 371 | WHERE handle = 'clunven'; 372 | 373 | ``` 374 | 375 |
376 | 377 | [🏠 Back to Table of Contents](#-table-of-content) 378 | 379 | ## 8. KDM Data Modeling Tool 380 | 381 |
382 |

🍿 Demo

383 | 384 | ### ✅ Download [the project XML file](https://raw.githubusercontent.com/datastaxdevs/workshop-cassandra-data-modeling/main/materials/kdm_sensor_data.xml). 385 | 386 | ### ✅ Open [the KDM tool](http://kdm.kashliev.com/). 387 | 388 | ### ✅ Import the project by selecting `Import Project` from the menu and specifying file `kdm_sensor_data.xml`. 389 | 390 | ![](images/kdm_01.png) 391 | 392 | ![](images/kdm_02.png) 393 | 394 | ### ✅ Explore the five data modeling steps supported by KDM. Note that the conceptual data model in Step 1 and queries in Step 2 are already defined. 395 | 396 | ![](images/kdm_03.png) 397 | 398 |
399 | 400 | [🏠 Back to Table of Contents](#-table-of-content) 401 | 402 | ## 9. Sensor Data Modeling 403 | 404 | A [GitHub](https://github.com) account may be required to run this hands-on lab in Gitpod. 405 | 406 | ### ✅ [Sensor Data Modeling](https://gitpod.io/#https://github.com/DataStax-Academy/workshop-cassandra-data-modeling-sensor-data/) 407 | 408 | [🏠 Back to Table of Contents](#-table-of-content) 409 | 410 | 411 | ## 10. Homework 412 | 413 | 1. Complete [Working with Data Types](#7-working-with-data-types). Take a screenshot of the CQL Console showing the rows in tables 414 | `table_with_udt` and `table_with_counters` before _and_ after executing the DELETE statements. 415 | 416 | 2. Complete the mini-course [Time Series Data Modeling](https://www.datastax.com/learn/data-modeling-by-example/time-series-model). Take a screenshot of the final screen of the practice lab, with the console output at the right. 417 | 418 | 3. [Submit your homework](https://forms.gle/Z69y4MM3SpEDg7nt5) and be awarded a nice verifiable badge! 419 | 420 | [🏠 Back to Table of Contents](#-table-of-content) 421 | 422 | ## 11. What's NEXT ? 423 | 424 | We've just scratched the surface of what you can do using Astra DB, built on Apache Cassandra. 425 | 426 | Go take a look at [DataStax for Developers](https://www.datastax.com/dev) to see what else is possible. 427 | There's plenty to dig into! 428 | 429 | Congratulations: you made to the end of today's workshop. 430 | 431 | ![Badge](images/badge_data_modeling.png) 432 | 433 | **... and see you at our next workshop!** 434 | 435 | > Sincerely yours, The DataStax Developers 436 | -------------------------------------------------------------------------------- /astra.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Apache Cassandra Data Modeling", 3 | "description": "This session looks at how to effectively design a data model for your application. You’ll leave knowing how to create data models that scale effectively as your system grows ", 4 | "duration": "120 minutes", 5 | "skillLevel": "Beginner", 6 | "language":["CQL"], 7 | "stack":["cassandra"], 8 | "githubUrl": "https://github.com/datastaxdevs/workshop-cassandra-data-modeling/", 9 | "badge": "https://media.badgr.com/uploads/badges/5dee8148-ec34-43e2-a4ec-68a501130cfd.png", 10 | "youTubeUrl": [ "https://www.youtube.com/watch?v=xrDfE74QnSE"], 11 | "tags": [ 12 | { "name": "workshop" }, 13 | { "name": "nosql" }, 14 | { "name": "cassandra" }, 15 | { "name": "cql" } 16 | ], 17 | "category": "workshop", 18 | "usecases": [] 19 | } 20 | -------------------------------------------------------------------------------- /images/badge_data_modeling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/workshop-cassandra-data-modeling/d7a1422b262e044512e85b0daea0fcd9f4e19652/images/badge_data_modeling.png -------------------------------------------------------------------------------- /images/create_astra_db_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/workshop-cassandra-data-modeling/d7a1422b262e044512e85b0daea0fcd9f4e19652/images/create_astra_db_button.png -------------------------------------------------------------------------------- /images/illustrations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/workshop-cassandra-data-modeling/d7a1422b262e044512e85b0daea0fcd9f4e19652/images/illustrations.png -------------------------------------------------------------------------------- /images/kdm_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/workshop-cassandra-data-modeling/d7a1422b262e044512e85b0daea0fcd9f4e19652/images/kdm_01.png -------------------------------------------------------------------------------- /images/kdm_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/workshop-cassandra-data-modeling/d7a1422b262e044512e85b0daea0fcd9f4e19652/images/kdm_02.png -------------------------------------------------------------------------------- /images/kdm_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/workshop-cassandra-data-modeling/d7a1422b262e044512e85b0daea0fcd9f4e19652/images/kdm_03.png -------------------------------------------------------------------------------- /images/killrcoda_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/workshop-cassandra-data-modeling/d7a1422b262e044512e85b0daea0fcd9f4e19652/images/killrcoda_01.png -------------------------------------------------------------------------------- /images/killrcoda_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/workshop-cassandra-data-modeling/d7a1422b262e044512e85b0daea0fcd9f4e19652/images/killrcoda_02.png -------------------------------------------------------------------------------- /images/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/workshop-cassandra-data-modeling/d7a1422b262e044512e85b0daea0fcd9f4e19652/images/splash.png -------------------------------------------------------------------------------- /materials/kdm_sensor_data.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | {"records":["Sensor.id,Temperature.timestamp"],"Temperature":["Sensor.id,Temperature.timestamp"]} 117 | 118 | 119 | 120 | 121 | simple 122 | 123 | 124 |
125 |
126 |
127 |
128 | Network.name
129 |
130 |
131 |
132 |
133 | 134 | ASC 135 |
136 | 137 | 138 |
139 |
140 |
141 |
142 | Network.description
143 |
144 |
145 |
146 |
147 |
148 | 149 | 150 |
151 |
152 |
153 |
154 | Network.region
155 |
156 |
157 |
158 |
159 |
160 | 161 | 162 |
163 |
164 |
165 |
166 | Network.number of sensors
167 |
168 |
169 |
170 |
171 |
172 | 173 | Find information about all networks; order by name (asc) 174 |
175 | 176 | 177 | simple 178 | 179 | 180 |
181 | Network.name
182 |
183 | 184 | value 185 |
186 | 187 | 188 |
189 | Sensor.id
190 |
191 |
192 | 193 | 194 |
195 | Sensor.latitude
196 |
197 |
198 | 199 | 200 |
201 | Sensor.longitude
202 |
203 |
204 | 205 | 206 |
207 | Temperature.value
208 |
209 |
210 | 211 | 212 |
213 | Temperature.date
214 |
215 | 216 | DESC 217 |
218 | 219 | 220 |
221 | Temperature.hour
222 |
223 | 224 | DESC 225 |
226 | 227 | Find hourly average temperatures for every sensor in a specified network for a given date range; order by date (desc) and hour (desc) 228 |
229 | 230 | 231 | simple 232 | 233 | 234 |
235 |
236 |
237 | Network.name
238 |
239 |
240 |
241 | 242 | value 243 |
244 | 245 | 246 |
247 |
248 |
249 | Sensor.id
250 |
251 |
252 |
253 |
254 | 255 | 256 |
257 |
258 |
259 | Sensor.latitude
260 |
261 |
262 |
263 |
264 | 265 | 266 |
267 |
268 |
269 | Sensor.longitude
270 |
271 |
272 |
273 |
274 | 275 | 276 |
277 |
278 |
279 | Sensor.characteristics
280 |
281 |
282 |
283 |
284 | 285 | Find information about all sensors in a specified network 286 |
287 | 288 | 289 | simple 290 | 291 | 292 |
293 |
294 |
295 | Sensor.id
296 |
297 |
298 |
299 | 300 | value 301 |
302 | 303 | 304 |
305 |
306 |
307 | Temperature.date
308 |
309 |
310 |
311 | 312 | value 313 |
314 | 315 | 316 |
317 |
318 |
319 | Temperature.timestamp
320 |
321 |
322 |
323 | 324 | DESC 325 |
326 | 327 | 328 |
329 |
330 |
331 | Temperature.value
332 |
333 |
334 |
335 |
336 | 337 | Find raw measurements for a particular sensor on a specified date; order by timestamp (desc) 338 |
339 |
340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | ASC 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | DESC 370 | 371 | 372 | 373 | 374 | DESC 375 | 376 | 377 | 378 | 379 | ASC 380 | 381 | 382 | 383 | ASC 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | DESC 400 | 401 | 402 | 403 | 404 | DESC 405 | 406 | 407 | 408 | 409 | ASC 410 | 411 | 412 | 413 | ASC 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | ASC 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | DESC 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | DESC 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | ASC 491 | 492 | 493 | 494 | 495 | DESC 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | ASC 511 | 512 | 513 | 514 | 515 | DESC 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | {"table0":"","table1":"","sensors_by_network":"","temperatures_by_sensor":""} 524 | 525 |
526 | -------------------------------------------------------------------------------- /materials/kdm_sensor_data_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | {"records":["Sensor.id,Temperature.timestamp"],"Temperature":["Sensor.id,Temperature.timestamp"]} 117 | 118 | 119 | 120 | 121 | simple 122 | 123 | 124 |
125 |
126 |
127 |
128 |
129 | Network.name
130 |
131 |
132 |
133 |
134 |
135 | 136 | ASC 137 |
138 | 139 | 140 |
141 |
142 |
143 |
144 |
145 | Network.description
146 |
147 |
148 |
149 |
150 |
151 |
152 | 153 | 154 |
155 |
156 |
157 |
158 |
159 | Network.region
160 |
161 |
162 |
163 |
164 |
165 |
166 | 167 | 168 |
169 |
170 |
171 |
172 |
173 | Network.number of sensors
174 |
175 |
176 |
177 |
178 |
179 |
180 | 181 | Find information about all networks; order by name (asc) 182 |
183 | 184 | 185 | simple 186 | 187 | 188 |
189 |
190 | Network.name
191 |
192 |
193 | 194 | value 195 |
196 | 197 | 198 |
199 |
200 | Sensor.id
201 |
202 |
203 |
204 | 205 | 206 |
207 |
208 | Sensor.latitude
209 |
210 |
211 |
212 | 213 | 214 |
215 |
216 | Sensor.longitude
217 |
218 |
219 |
220 | 221 | 222 |
223 |
224 | Temperature.value
225 |
226 |
227 |
228 | 229 | 230 |
231 |
232 | Temperature.date
233 |
234 |
235 | 236 | DESC 237 |
238 | 239 | 240 |
241 |
242 | Temperature.hour
243 |
244 |
245 | 246 | DESC 247 |
248 | 249 | Find hourly average temperatures for every sensor in a specified network for a given date range; order by date (desc) and hour (desc) 250 |
251 | 252 | 253 | simple 254 | 255 | 256 |
257 |
258 |
259 |
260 | Network.name
261 |
262 |
263 |
264 |
265 | 266 | value 267 |
268 | 269 | 270 |
271 |
272 |
273 |
274 | Sensor.id
275 |
276 |
277 |
278 |
279 |
280 | 281 | 282 |
283 |
284 |
285 |
286 | Sensor.latitude
287 |
288 |
289 |
290 |
291 |
292 | 293 | 294 |
295 |
296 |
297 |
298 | Sensor.longitude
299 |
300 |
301 |
302 |
303 |
304 | 305 | 306 |
307 |
308 |
309 |
310 | Sensor.characteristics
311 |
312 |
313 |
314 |
315 |
316 | 317 | Find information about all sensors in a specified network 318 |
319 | 320 | 321 | simple 322 | 323 | 324 |
325 |
326 |
327 |
328 | Sensor.id
329 |
330 |
331 |
332 |
333 | 334 | value 335 |
336 | 337 | 338 |
339 |
340 |
341 |
342 | Temperature.date
343 |
344 |
345 |
346 |
347 | 348 | value 349 |
350 | 351 | 352 |
353 |
354 |
355 |
356 | Temperature.timestamp
357 |
358 |
359 |
360 |
361 | 362 | DESC 363 |
364 | 365 | 366 |
367 |
368 |
369 |
370 | Temperature.value
371 |
372 |
373 |
374 |
375 |
376 | 377 | Find raw measurements for a particular sensor on a specified date; order by timestamp (desc) 378 |
379 |
380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | ASC 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | DESC 410 | 411 | 412 | 413 | 414 | DESC 415 | 416 | 417 | 418 | 419 | ASC 420 | 421 | 422 | 423 | ASC 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | DESC 440 | 441 | 442 | 443 | 444 | DESC 445 | 446 | 447 | 448 | 449 | ASC 450 | 451 | 452 | 453 | ASC 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | ASC 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | DESC 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | DESC 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | ASC 531 | 532 | 533 | 534 | 535 | DESC 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | ASC 551 | 552 | 553 | 554 | 555 | DESC 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | {"table0":"","table1":"","sensors_by_network":"","temperatures_by_sensor":""} 564 | 565 | 566 | {"0":{"listOfInputs":"sensors,name,description,region,numberofsensors","listOfSelectValues":"TEXT,K,TEXT,,TEXT,,TEXT,"},"1":{"listOfInputs":"temperatures_by_network,name,date,hour,timestamp,id,latitude,longitude,value","listOfSelectValues":"TEXT,K,TEXT,cdown,TEXT,cdown,TEXT,cup,TEXT,cup,TEXT,,TEXT,,TEXT,"},"2":{"listOfInputs":"sensors_by_network,name,id,latitude,longitude,characteristics","listOfSelectValues":"TEXT,K,TEXT,cup,TEXT,,TEXT,,SET,TEXT,"},"3":{"listOfInputs":"temperatures_by_sensor,id,date,timestamp,value","listOfSelectValues":"TEXT,K,TEXT,K,TEXT,cdown,TEXT,"},"highlightedTables":["table0","table1","sensors_by_network","temperatures_by_sensor"]} 567 |
568 | -------------------------------------------------------------------------------- /slides/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/workshop-cassandra-data-modeling/d7a1422b262e044512e85b0daea0fcd9f4e19652/slides/slides.pdf --------------------------------------------------------------------------------