├── .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 | 
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 | - 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 |
60 | - You will need enough "real estate" on screen, we will ask you to open a few windows and it would not fit on mobiles (tablets should be OK)
61 |
- You will need an Astra account: don't worry, we'll work through that in the following
62 |
- As "Intermediate level" we expect you to know what java and Spring are.
63 |
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 | 
391 |
392 | 
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 | 
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 | 
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
--------------------------------------------------------------------------------