Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Cassandra

  • A production grade NoSQL database.

  • Can be distributed across servers, nodes, etc.

  • Replication of database is supported for high degree of redundancy and speed.

  • Uses CQL, a subset of SQL for querying.

  • Works seamlesly together with Spark and its corresponding distributed structure.

  • Installation of Cassandra is explained in the Installation chapter.

Spinning up a local Cassandra instance

In a terminal, first time:
docker run --name my_cassandra -p 9042:9042 cassandra:latest
... and later:
docker start my_cassandra

.. or in Docker Desktop:

  • Run the cassandra docker image with optional settings, opening 9042 port and setting a name.

  • Later, simply run the container with the name you chose.

Connect to the Cassandra cluster from Python.

# Connecting to Cassandra
from cassandra.cluster import Cluster
cluster = Cluster(['localhost'], port=9042)
session = cluster.connect()

Keyspace

  • In Cassandra database tables are stored in keyspaces (basically a distributed database).

  • These have parameters controlling their distribution on nodes/servers and redundancy.

  • We will use the simplest form locally.

# Set up new keyspace (first time only)
#                                              name of keyspace                        replication strategy           replication factor
session.execute("CREATE KEYSPACE IF NOT EXISTS my_first_keyspace WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };")
<cassandra.cluster.ResultSet at 0x10bba9f70>

Create a table

  • IF NOT EXISTS makes sure we do not overwrite existing tables

# Create a new table (first time only)
session.set_keyspace('my_first_keyspace')
session.execute("DROP TABLE IF EXISTS my_first_keyspace.my_first_table;") # Starting from scratch every time
session.execute("CREATE TABLE IF NOT EXISTS my_first_table (ind int PRIMARY KEY, company text, model text);")
<cassandra.cluster.ResultSet at 0x10d439b80>

Inserting and reading data

# Insert some data (ind is the primary key, must be unique)
session.execute("INSERT INTO my_first_table (ind, company, model) VALUES (1, 'Tesla', 'Model S');")
session.execute("INSERT INTO my_first_table (ind, company, model) VALUES (2, 'Tesla', 'Model 3');")
session.execute("INSERT INTO my_first_table (ind, company, model) VALUES (3, 'Polestar', '3');")
<cassandra.cluster.ResultSet at 0x10d439c10>
# Query the data
rows = session.execute("SELECT * FROM my_first_table;")
for i in rows:
    print(i)
Row(ind=1, company='Tesla', model='Model S')
Row(ind=2, company='Tesla', model='Model 3')
Row(ind=3, company='Polestar', model='3')

Case sensitivity

  • Cassandra is by default case insensitive in column names.

  • To use column names with capital letters, use double quotation marks both when creating tables and when inserting data.

  • The effect of insensitivity may be surprising.

    • Look carefully at the use of quotation marks and error message below.

session.set_keyspace('my_first_keyspace')
session.execute("DROP TABLE IF EXISTS my_first_keyspace.case_insensitive;") # Starting from scratch every time
session.execute("CREATE TABLE IF NOT EXISTS case_insensitive (Capital int PRIMARY KEY, Letters text, Everywhere text);")
session.execute("DROP TABLE IF EXISTS my_first_keyspace.case_sensitive;") # Starting from scratch every time
session.execute("CREATE TABLE IF NOT EXISTS case_sensitive (\"Capital\" int PRIMARY KEY, \"Letters\" text, \"Everywhere\" text);")
<cassandra.cluster.ResultSet at 0x10d440680>
session.execute("INSERT INTO case_insensitive (Capital, Letters, Everywhere) VALUES (1, 'Tesla', 'Model S');")
<cassandra.cluster.ResultSet at 0x10ca10aa0>
session.execute("INSERT INTO case_sensitive (Capital, Letters, Everywhere) VALUES (1, 'Tesla', 'Model S');")
---------------------------------------------------------------------------
InvalidRequest                            Traceback (most recent call last)
Cell In[8], line 1
----> 1 session.execute("INSERT INTO case_sensitive (Capital, Letters, Everywhere) VALUES (1, 'Tesla', 'Model S');")

File cassandra/cluster.py:2642, in cassandra.cluster.Session.execute()
-> 2642 'Could not get source, probably due dynamically evaluated source code.'

File cassandra/cluster.py:5013, in cassandra.cluster.ResponseFuture.result()
-> 5013 'Could not get source, probably due dynamically evaluated source code.'

InvalidRequest: Error from server: code=2200 [Invalid query] message="Undefined column name capital in table my_first_keyspace.case_sensitive"
session.execute("INSERT INTO case_sensitive (\"Capital\", \"Letters\", \"Everywhere\") VALUES (1, 'Tesla', 'Model S');")
<cassandra.cluster.ResultSet at 0x10d439310>
# Query the data
rows = session.execute("SELECT * FROM case_insensitive;")
for i in rows:
    print(i)
rows = session.execute("SELECT * FROM case_sensitive;")
for i in rows:
    print(i)
Row(capital=1, everywhere='Model S', letters='Tesla')
Row(Capital=1, Everywhere='Model S', Letters='Tesla')

Asyncronous writing

  • If your application is very data intensive, waiting for a response is not productive.

  • Writing asyncronously sends the data but does not pause for reply.

session.execute_async("INSERT INTO my_first_table (ind, company, model) VALUES (5, 'Volkswagen', 'ID.3');")
<ResponseFuture: query='<SimpleStatement query="INSERT INTO my_first_table (ind, company, model) VALUES (5, 'Volkswagen', 'ID.3');", consistency=Not Set>' request_id=63 result=(no result yet) exception=None coordinator_host=None>
# Query the data
rows = session.execute("SELECT * FROM my_first_table;")
for i in rows:
    print(i)
Row(ind=1, company='Tesla', model='Model S')
Row(ind=2, company='Tesla', model='Model 3')
Row(ind=3, company='Polestar', model='3')
# More specific query
prepared_statement = session.prepare("SELECT * FROM my_first_table WHERE company=? ALLOW FILTERING;")
teslas = session.execute(prepared_statement, ['Tesla'])
for i in teslas:
    print(i)
Row(ind=1, company='Tesla', model='Model S')
Row(ind=2, company='Tesla', model='Model 3')

Cassandra filtering

Cassandra is inherently a distributed production database. Selecting as above may require downloading all data from a node, then filtering based on the WHERE part (only PRIMARY KEYs are centrally known). Solutions:

  • If the table is small or most of the data will satisfy the query, add ALLOW FILTERING at the end of the query (not recommended if not known).

  • Or make sure the WHERE clause points to one of the keys (see below).

# Create a new table (observe keys)
session.execute("DROP TABLE IF EXISTS my_first_keyspace.car_table;")
session.execute("CREATE TABLE IF NOT EXISTS car_table (company text, model text, PRIMARY KEY(company, model));")
<cassandra.cluster.ResultSet at 0x10d440c50>
# Insert some data (combination of company and model must be unique)
session.execute("INSERT INTO car_table (company, model) VALUES ('Tesla', 'Model S');")
session.execute("INSERT INTO car_table (company, model) VALUES ('Tesla', 'Model 3');")
session.execute("INSERT INTO car_table (company, model) VALUES ('Polestar', '3');")
session.execute("INSERT INTO car_table (company, model) VALUES ('Volkswagen', 'ID.4');")
<cassandra.cluster.ResultSet at 0x10d459370>
# More specific query now works
prepared_statement = session.prepare("SELECT * FROM car_table WHERE company=?;")
teslas = session.execute(prepared_statement, ['Tesla'])
for i in teslas:
    print(i)
Row(company='Tesla', model='Model 3')
Row(company='Tesla', model='Model S')

Partitions

  • Cassandra databases are usually replicated over different nodes.

  • Data is stored in partitions (subsets) which have local copys.

  • The primary key, e.g., PRIMARY KEY(company, model), is used in partitioning.

    • The first part, e.g., company, is most important.

    • All cars from a company will be located together, aiming for quicker queries.

Unique IDs

  • In MySQL one could use the attribute AUTO_INCREMENT on integer IDs to automatically make a new unique index when inserting data.

  • This would cause unreasonable overhead in a distributed database.

  • UUIDs are used instead.

    • Universally Unique Identifiers are typically 128-bit random bit sequences with extremely low probability of duplication.

    • Cassandra uses a timeuuid type to combine a timestamp and uuid in one.

# Create a new table (first time only)
session.set_keyspace('my_first_keyspace')
session.execute("DROP TABLE IF EXISTS my_first_keyspace.table_with_uuid;")
session.execute("CREATE TABLE IF NOT EXISTS table_with_uuid (id timeuuid PRIMARY KEY, company text, model text, price float);")
<cassandra.cluster.ResultSet at 0x10d438ec0>
session.execute("INSERT INTO table_with_uuid (id, company, model, price) VALUES (now(), 'Tesla', 'Model S', 20000.0);")
session.execute("INSERT INTO table_with_uuid (id, company, model, price) VALUES (now(), 'Tesla', 'Model S', 21000.0);")
session.execute("INSERT INTO table_with_uuid (id, company, model, price) VALUES (now(), 'Oldsmobile', 'Model 6C', 135000.0);")
<cassandra.cluster.ResultSet at 0x10d44de20>
from cassandra.util import datetime_from_uuid1

# Query the data
rows = session.execute("SELECT * FROM table_with_uuid;")
for i in rows:
    print(i)
    # Extract the timestamp from Cassandra's timeuuid
    print("Datetime:", datetime_from_uuid1(i.id))
Row(id=UUID('35803a50-9aff-11f1-abaa-c1eea8c331dd'), company='Tesla', model='Model S', price=21000.0)
Datetime: 2026-08-18 12:20:33.013000
Row(id=UUID('358172d0-9aff-11f1-abaa-c1eea8c331dd'), company='Oldsmobile', model='Model 6C', price=135000.0)
Datetime: 2026-08-18 12:20:33.021000
Row(id=UUID('357f28e0-9aff-11f1-abaa-c1eea8c331dd'), company='Tesla', model='Model S', price=20000.0)
Datetime: 2026-08-18 12:20:33.006000

JSON in Cassandra

Read previously saved JSON file forecast.json to memory

import json
with open('../3_APIs/downloads/forecast.json', 'r') as f:
    forecast = json.load(f)
# Inspect JSON file
forecast.__str__()
"{'cod': '200', 'message': 0, 'cnt': 40, 'list': [{'dt': 1787065200, 'main': {'temp': 301.14, 'feels_like': 302.06, 'temp_min': 298.61, 'temp_max': 301.14, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 999, 'humidity': 55, 'temp_kf': 2.53, 'dew_point': 291.26}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 4}, 'wind': {'speed': 5.02, 'deg': 278, 'gust': 5.42}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-18 15:00:00'}, {'dt': 1787076000, 'main': {'temp': 299.57, 'feels_like': 299.57, 'temp_min': 298.15, 'temp_max': 299.57, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 999, 'humidity': 55, 'temp_kf': 1.42, 'dew_point': 289.81}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02d'}], 'clouds': {'all': 14}, 'wind': {'speed': 4.07, 'deg': 271, 'gust': 4.68}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-18 18:00:00'}, {'dt': 1787086800, 'main': {'temp': 296.04, 'feels_like': 296.16, 'temp_min': 296.04, 'temp_max': 296.04, 'pressure': 1018, 'sea_level': 1018, 'grnd_level': 1001, 'humidity': 68, 'temp_kf': 0, 'dew_point': 289.75}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'clouds': {'all': 100}, 'wind': {'speed': 1.11, 'deg': 175, 'gust': 2.02}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-18 21:00:00'}, {'dt': 1787097600, 'main': {'temp': 296.18, 'feels_like': 296.26, 'temp_min': 296.18, 'temp_max': 296.18, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 1000, 'humidity': 66, 'temp_kf': 0, 'dew_point': 289.55}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'clouds': {'all': 100}, 'wind': {'speed': 3.15, 'deg': 112, 'gust': 3.43}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-19 00:00:00'}, {'dt': 1787108400, 'main': {'temp': 295.72, 'feels_like': 295.76, 'temp_min': 295.72, 'temp_max': 295.72, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 999, 'humidity': 66, 'temp_kf': 0, 'dew_point': 289.03}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'clouds': {'all': 100}, 'wind': {'speed': 1.47, 'deg': 313, 'gust': 1.49}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-19 03:00:00'}, {'dt': 1787119200, 'main': {'temp': 295.25, 'feels_like': 295.29, 'temp_min': 295.25, 'temp_max': 295.25, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 1000, 'humidity': 68, 'temp_kf': 0, 'dew_point': 289.13}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'clouds': {'all': 100}, 'wind': {'speed': 0.99, 'deg': 109, 'gust': 0.7}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-19 06:00:00'}, {'dt': 1787130000, 'main': {'temp': 295.37, 'feels_like': 295.48, 'temp_min': 295.37, 'temp_max': 295.37, 'pressure': 1018, 'sea_level': 1018, 'grnd_level': 1001, 'humidity': 70, 'temp_kf': 0, 'dew_point': 289.54}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 100}, 'wind': {'speed': 4.25, 'deg': 189, 'gust': 3.99}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-19 09:00:00'}, {'dt': 1787140800, 'main': {'temp': 300.1, 'feels_like': 300.35, 'temp_min': 300.1, 'temp_max': 300.1, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 1000, 'humidity': 47, 'temp_kf': 0, 'dew_point': 286.62}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 100}, 'wind': {'speed': 2.58, 'deg': 233, 'gust': 1.13}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-19 12:00:00'}, {'dt': 1787151600, 'main': {'temp': 300.93, 'feels_like': 301.27, 'temp_min': 300.93, 'temp_max': 300.93, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 998, 'humidity': 49, 'temp_kf': 0, 'dew_point': 287.95}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 90}, 'wind': {'speed': 2.93, 'deg': 284, 'gust': 4.24}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-19 15:00:00'}, {'dt': 1787162400, 'main': {'temp': 299.52, 'feels_like': 299.52, 'temp_min': 299.52, 'temp_max': 299.52, 'pressure': 1015, 'sea_level': 1015, 'grnd_level': 998, 'humidity': 54, 'temp_kf': 0, 'dew_point': 288.87}, 'weather': [{'id': 803, 'main': 'Clouds', 'description': 'broken clouds', 'icon': '04d'}], 'clouds': {'all': 69}, 'wind': {'speed': 3.32, 'deg': 285, 'gust': 4.53}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-19 18:00:00'}, {'dt': 1787173200, 'main': {'temp': 295.92, 'feels_like': 296.13, 'temp_min': 295.92, 'temp_max': 295.92, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 1000, 'humidity': 72, 'temp_kf': 0, 'dew_point': 290.64}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 4}, 'wind': {'speed': 0.57, 'deg': 126, 'gust': 3.55}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-19 21:00:00'}, {'dt': 1787184000, 'main': {'temp': 294.11, 'feels_like': 294.45, 'temp_min': 294.11, 'temp_max': 294.11, 'pressure': 1018, 'sea_level': 1018, 'grnd_level': 1001, 'humidity': 84, 'temp_kf': 0, 'dew_point': 291.5}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 4}, 'wind': {'speed': 2.79, 'deg': 111, 'gust': 3.04}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-20 00:00:00'}, {'dt': 1787194800, 'main': {'temp': 293.52, 'feels_like': 293.83, 'temp_min': 293.52, 'temp_max': 293.52, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 1000, 'humidity': 85, 'temp_kf': 0, 'dew_point': 291.07}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 5}, 'wind': {'speed': 1.27, 'deg': 96, 'gust': 1.89}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-20 03:00:00'}, {'dt': 1787205600, 'main': {'temp': 292.41, 'feels_like': 292.74, 'temp_min': 292.41, 'temp_max': 292.41, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 999, 'humidity': 90, 'temp_kf': 0, 'dew_point': 290.95}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 2}, 'wind': {'speed': 0.73, 'deg': 224, 'gust': 0.15}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-20 06:00:00'}, {'dt': 1787216400, 'main': {'temp': 295.47, 'feels_like': 295.64, 'temp_min': 295.47, 'temp_max': 295.47, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 1000, 'humidity': 72, 'temp_kf': 0, 'dew_point': 290.1}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 0}, 'wind': {'speed': 2.04, 'deg': 233, 'gust': 0.72}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-20 09:00:00'}, {'dt': 1787227200, 'main': {'temp': 298.35, 'feels_like': 298.52, 'temp_min': 298.35, 'temp_max': 298.35, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 1000, 'humidity': 61, 'temp_kf': 0, 'dew_point': 289.52}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 2}, 'wind': {'speed': 4.46, 'deg': 252, 'gust': 3.36}, 'visibility': 9552, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-20 12:00:00'}, {'dt': 1787238000, 'main': {'temp': 301.93, 'feels_like': 302.31, 'temp_min': 301.93, 'temp_max': 301.93, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 996, 'humidity': 48, 'temp_kf': 0, 'dew_point': 288.18}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02d'}], 'clouds': {'all': 14}, 'wind': {'speed': 7.21, 'deg': 303, 'gust': 8.3}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-20 15:00:00'}, {'dt': 1787248800, 'main': {'temp': 300.38, 'feels_like': 301, 'temp_min': 300.38, 'temp_max': 300.38, 'pressure': 1012, 'sea_level': 1012, 'grnd_level': 995, 'humidity': 53, 'temp_kf': 0, 'dew_point': 289.24}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 7}, 'wind': {'speed': 5.05, 'deg': 340, 'gust': 9.39}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-20 18:00:00'}, {'dt': 1787259600, 'main': {'temp': 295.39, 'feels_like': 295.58, 'temp_min': 295.39, 'temp_max': 295.39, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 998, 'humidity': 73, 'temp_kf': 0, 'dew_point': 290.62}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 1}, 'wind': {'speed': 4.2, 'deg': 120, 'gust': 3.04}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-20 21:00:00'}, {'dt': 1787270400, 'main': {'temp': 294.03, 'feels_like': 294.29, 'temp_min': 294.03, 'temp_max': 294.03, 'pressure': 1015, 'sea_level': 1015, 'grnd_level': 998, 'humidity': 81, 'temp_kf': 0, 'dew_point': 290.83}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 0}, 'wind': {'speed': 2.27, 'deg': 132, 'gust': 1.64}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-21 00:00:00'}, {'dt': 1787281200, 'main': {'temp': 292.99, 'feels_like': 293.3, 'temp_min': 292.99, 'temp_max': 292.99, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 997, 'humidity': 87, 'temp_kf': 0, 'dew_point': 291}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 0}, 'wind': {'speed': 1.56, 'deg': 158, 'gust': 1.56}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-21 03:00:00'}, {'dt': 1787292000, 'main': {'temp': 292.21, 'feels_like': 292.55, 'temp_min': 292.21, 'temp_max': 292.21, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 996, 'humidity': 91, 'temp_kf': 0, 'dew_point': 291.04}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 0}, 'wind': {'speed': 1.27, 'deg': 167, 'gust': 0.96}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-21 06:00:00'}, {'dt': 1787302800, 'main': {'temp': 294.71, 'feels_like': 294.93, 'temp_min': 294.71, 'temp_max': 294.71, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 997, 'humidity': 77, 'temp_kf': 0, 'dew_point': 290.47}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 0}, 'wind': {'speed': 2.31, 'deg': 190, 'gust': 0.9}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-21 09:00:00'}, {'dt': 1787313600, 'main': {'temp': 297.99, 'feels_like': 298.17, 'temp_min': 297.99, 'temp_max': 297.99, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 997, 'humidity': 63, 'temp_kf': 0, 'dew_point': 289.94}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 2}, 'wind': {'speed': 4.56, 'deg': 252, 'gust': 3.65}, 'visibility': 8998, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-21 12:00:00'}, {'dt': 1787324400, 'main': {'temp': 300.31, 'feels_like': 301.06, 'temp_min': 300.31, 'temp_max': 300.31, 'pressure': 1011, 'sea_level': 1011, 'grnd_level': 994, 'humidity': 55, 'temp_kf': 0, 'dew_point': 289.64}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02d'}], 'clouds': {'all': 11}, 'wind': {'speed': 5.57, 'deg': 300, 'gust': 6.8}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-21 15:00:00'}, {'dt': 1787335200, 'main': {'temp': 299.62, 'feels_like': 299.62, 'temp_min': 299.62, 'temp_max': 299.62, 'pressure': 1010, 'sea_level': 1010, 'grnd_level': 993, 'humidity': 58, 'temp_kf': 0, 'dew_point': 290.23}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 7}, 'wind': {'speed': 6.78, 'deg': 328, 'gust': 7.75}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-21 18:00:00'}, {'dt': 1787346000, 'main': {'temp': 295.09, 'feels_like': 295.38, 'temp_min': 295.09, 'temp_max': 295.09, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 996, 'humidity': 78, 'temp_kf': 0, 'dew_point': 291.16}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 0}, 'wind': {'speed': 4.01, 'deg': 96, 'gust': 4.45}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-21 21:00:00'}, {'dt': 1787356800, 'main': {'temp': 294.23, 'feels_like': 294.53, 'temp_min': 294.23, 'temp_max': 294.23, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 997, 'humidity': 82, 'temp_kf': 0, 'dew_point': 291.25}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 0}, 'wind': {'speed': 3.56, 'deg': 125, 'gust': 3.1}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-22 00:00:00'}, {'dt': 1787367600, 'main': {'temp': 293.32, 'feels_like': 293.69, 'temp_min': 293.32, 'temp_max': 293.32, 'pressure': 1012, 'sea_level': 1012, 'grnd_level': 995, 'humidity': 88, 'temp_kf': 0, 'dew_point': 291.46}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 5}, 'wind': {'speed': 1.55, 'deg': 140, 'gust': 1}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-22 03:00:00'}, {'dt': 1787378400, 'main': {'temp': 292.62, 'feels_like': 293.05, 'temp_min': 292.62, 'temp_max': 292.62, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 996, 'humidity': 93, 'temp_kf': 0, 'dew_point': 291.67}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 1}, 'wind': {'speed': 1.54, 'deg': 165, 'gust': 1.12}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-22 06:00:00'}, {'dt': 1787389200, 'main': {'temp': 294.39, 'feels_like': 294.74, 'temp_min': 294.39, 'temp_max': 294.39, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 997, 'humidity': 83, 'temp_kf': 0, 'dew_point': 291.58}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02d'}], 'clouds': {'all': 18}, 'wind': {'speed': 2.71, 'deg': 165, 'gust': 1.12}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-22 09:00:00'}, {'dt': 1787400000, 'main': {'temp': 297.12, 'feels_like': 297.43, 'temp_min': 297.12, 'temp_max': 297.12, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 997, 'humidity': 71, 'temp_kf': 0, 'dew_point': 291.32}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02d'}], 'clouds': {'all': 19}, 'wind': {'speed': 3.98, 'deg': 255, 'gust': 2.62}, 'visibility': 9627, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-22 12:00:00'}, {'dt': 1787410800, 'main': {'temp': 299.26, 'feels_like': 299.26, 'temp_min': 299.26, 'temp_max': 299.26, 'pressure': 1011, 'sea_level': 1011, 'grnd_level': 995, 'humidity': 57, 'temp_kf': 0, 'dew_point': 289.67}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02d'}], 'clouds': {'all': 12}, 'wind': {'speed': 3.97, 'deg': 278, 'gust': 4.75}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-22 15:00:00'}, {'dt': 1787421600, 'main': {'temp': 298.27, 'feels_like': 298.35, 'temp_min': 298.27, 'temp_max': 298.27, 'pressure': 1011, 'sea_level': 1011, 'grnd_level': 995, 'humidity': 58, 'temp_kf': 0, 'dew_point': 289.29}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 6}, 'wind': {'speed': 1.32, 'deg': 301, 'gust': 3.71}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-22 18:00:00'}, {'dt': 1787432400, 'main': {'temp': 294, 'feels_like': 294.15, 'temp_min': 294, 'temp_max': 294, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 997, 'humidity': 77, 'temp_kf': 0, 'dew_point': 289.98}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 0}, 'wind': {'speed': 4.75, 'deg': 131, 'gust': 3.57}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-22 21:00:00'}, {'dt': 1787443200, 'main': {'temp': 292.59, 'feels_like': 292.76, 'temp_min': 292.59, 'temp_max': 292.59, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 998, 'humidity': 83, 'temp_kf': 0, 'dew_point': 289.91}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 0}, 'wind': {'speed': 4.45, 'deg': 113, 'gust': 4.91}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-23 00:00:00'}, {'dt': 1787454000, 'main': {'temp': 292.43, 'feels_like': 292.58, 'temp_min': 292.43, 'temp_max': 292.43, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 996, 'humidity': 83, 'temp_kf': 0, 'dew_point': 289.71}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 0}, 'wind': {'speed': 3.08, 'deg': 110, 'gust': 3.18}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-23 03:00:00'}, {'dt': 1787464800, 'main': {'temp': 291.91, 'feels_like': 292.09, 'temp_min': 291.91, 'temp_max': 291.91, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 997, 'humidity': 86, 'temp_kf': 0, 'dew_point': 289.85}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 0}, 'wind': {'speed': 1.26, 'deg': 97, 'gust': 1.81}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-23 06:00:00'}, {'dt': 1787475600, 'main': {'temp': 293.9, 'feels_like': 294.02, 'temp_min': 293.9, 'temp_max': 293.9, 'pressure': 1015, 'sea_level': 1015, 'grnd_level': 999, 'humidity': 76, 'temp_kf': 0, 'dew_point': 289.73}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 0}, 'wind': {'speed': 1.16, 'deg': 215, 'gust': 1.51}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-23 09:00:00'}, {'dt': 1787486400, 'main': {'temp': 295.64, 'feels_like': 295.72, 'temp_min': 295.64, 'temp_max': 295.64, 'pressure': 1015, 'sea_level': 1015, 'grnd_level': 999, 'humidity': 68, 'temp_kf': 0, 'dew_point': 289.04}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 4}, 'wind': {'speed': 4.47, 'deg': 251, 'gust': 3.49}, 'visibility': 9224, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-23 12:00:00'}], 'city': {'id': 2561668, 'name': 'Agadir', 'coord': {'lat': 30.4202, 'lon': -9.5982}, 'country': 'MA', 'population': 698310, 'timezone': 3600, 'sunrise': 1787033220, 'sunset': 1787080673}}"

Raw JSON

  • A simple, but not very efficient way of storing JSON data is to treat it as a text and save it directly to the database.

  • More efficient, with regard to transfer, is to compress the JSON data to a blob first.

    • Compression is automatic.

# Create a new table which treats the whole JSON as a blob, using the city id and the first dt as keys
session.set_keyspace('my_first_keyspace')
session.execute("DROP TABLE IF EXISTS my_first_keyspace.forecast_table;")
session.execute("CREATE TABLE IF NOT EXISTS forecast_table (city_id int, dt int, forecast blob, PRIMARY KEY(city_id, dt));")
<cassandra.cluster.ResultSet at 0x10d440f50>

Insert the forecast data into the table as text blob

session.execute("INSERT INTO forecast_table (city_id, dt, forecast) VALUES (%s, %s, textAsBlob(%s));", (forecast['city']['id'], forecast['list'][0]['dt'], forecast.__str__()))
<cassandra.cluster.ResultSet at 0x10bd23740>
# Query the data
forecast_rows = session.execute("SELECT * FROM forecast_table;")
print(forecast_rows.one()) # <- only one row
Row(city_id=2561668, dt=1787065200, forecast=b"{'cod': '200', 'message': 0, 'cnt': 40, 'list': [{'dt': 1787065200, 'main': {'temp': 301.14, 'feels_like': 302.06, 'temp_min': 298.61, 'temp_max': 301.14, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 999, 'humidity': 55, 'temp_kf': 2.53, 'dew_point': 291.26}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 4}, 'wind': {'speed': 5.02, 'deg': 278, 'gust': 5.42}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-18 15:00:00'}, {'dt': 1787076000, 'main': {'temp': 299.57, 'feels_like': 299.57, 'temp_min': 298.15, 'temp_max': 299.57, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 999, 'humidity': 55, 'temp_kf': 1.42, 'dew_point': 289.81}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02d'}], 'clouds': {'all': 14}, 'wind': {'speed': 4.07, 'deg': 271, 'gust': 4.68}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-18 18:00:00'}, {'dt': 1787086800, 'main': {'temp': 296.04, 'feels_like': 296.16, 'temp_min': 296.04, 'temp_max': 296.04, 'pressure': 1018, 'sea_level': 1018, 'grnd_level': 1001, 'humidity': 68, 'temp_kf': 0, 'dew_point': 289.75}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'clouds': {'all': 100}, 'wind': {'speed': 1.11, 'deg': 175, 'gust': 2.02}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-18 21:00:00'}, {'dt': 1787097600, 'main': {'temp': 296.18, 'feels_like': 296.26, 'temp_min': 296.18, 'temp_max': 296.18, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 1000, 'humidity': 66, 'temp_kf': 0, 'dew_point': 289.55}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'clouds': {'all': 100}, 'wind': {'speed': 3.15, 'deg': 112, 'gust': 3.43}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-19 00:00:00'}, {'dt': 1787108400, 'main': {'temp': 295.72, 'feels_like': 295.76, 'temp_min': 295.72, 'temp_max': 295.72, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 999, 'humidity': 66, 'temp_kf': 0, 'dew_point': 289.03}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'clouds': {'all': 100}, 'wind': {'speed': 1.47, 'deg': 313, 'gust': 1.49}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-19 03:00:00'}, {'dt': 1787119200, 'main': {'temp': 295.25, 'feels_like': 295.29, 'temp_min': 295.25, 'temp_max': 295.25, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 1000, 'humidity': 68, 'temp_kf': 0, 'dew_point': 289.13}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04n'}], 'clouds': {'all': 100}, 'wind': {'speed': 0.99, 'deg': 109, 'gust': 0.7}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-19 06:00:00'}, {'dt': 1787130000, 'main': {'temp': 295.37, 'feels_like': 295.48, 'temp_min': 295.37, 'temp_max': 295.37, 'pressure': 1018, 'sea_level': 1018, 'grnd_level': 1001, 'humidity': 70, 'temp_kf': 0, 'dew_point': 289.54}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 100}, 'wind': {'speed': 4.25, 'deg': 189, 'gust': 3.99}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-19 09:00:00'}, {'dt': 1787140800, 'main': {'temp': 300.1, 'feels_like': 300.35, 'temp_min': 300.1, 'temp_max': 300.1, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 1000, 'humidity': 47, 'temp_kf': 0, 'dew_point': 286.62}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 100}, 'wind': {'speed': 2.58, 'deg': 233, 'gust': 1.13}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-19 12:00:00'}, {'dt': 1787151600, 'main': {'temp': 300.93, 'feels_like': 301.27, 'temp_min': 300.93, 'temp_max': 300.93, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 998, 'humidity': 49, 'temp_kf': 0, 'dew_point': 287.95}, 'weather': [{'id': 804, 'main': 'Clouds', 'description': 'overcast clouds', 'icon': '04d'}], 'clouds': {'all': 90}, 'wind': {'speed': 2.93, 'deg': 284, 'gust': 4.24}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-19 15:00:00'}, {'dt': 1787162400, 'main': {'temp': 299.52, 'feels_like': 299.52, 'temp_min': 299.52, 'temp_max': 299.52, 'pressure': 1015, 'sea_level': 1015, 'grnd_level': 998, 'humidity': 54, 'temp_kf': 0, 'dew_point': 288.87}, 'weather': [{'id': 803, 'main': 'Clouds', 'description': 'broken clouds', 'icon': '04d'}], 'clouds': {'all': 69}, 'wind': {'speed': 3.32, 'deg': 285, 'gust': 4.53}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-19 18:00:00'}, {'dt': 1787173200, 'main': {'temp': 295.92, 'feels_like': 296.13, 'temp_min': 295.92, 'temp_max': 295.92, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 1000, 'humidity': 72, 'temp_kf': 0, 'dew_point': 290.64}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 4}, 'wind': {'speed': 0.57, 'deg': 126, 'gust': 3.55}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-19 21:00:00'}, {'dt': 1787184000, 'main': {'temp': 294.11, 'feels_like': 294.45, 'temp_min': 294.11, 'temp_max': 294.11, 'pressure': 1018, 'sea_level': 1018, 'grnd_level': 1001, 'humidity': 84, 'temp_kf': 0, 'dew_point': 291.5}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 4}, 'wind': {'speed': 2.79, 'deg': 111, 'gust': 3.04}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-20 00:00:00'}, {'dt': 1787194800, 'main': {'temp': 293.52, 'feels_like': 293.83, 'temp_min': 293.52, 'temp_max': 293.52, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 1000, 'humidity': 85, 'temp_kf': 0, 'dew_point': 291.07}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 5}, 'wind': {'speed': 1.27, 'deg': 96, 'gust': 1.89}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-20 03:00:00'}, {'dt': 1787205600, 'main': {'temp': 292.41, 'feels_like': 292.74, 'temp_min': 292.41, 'temp_max': 292.41, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 999, 'humidity': 90, 'temp_kf': 0, 'dew_point': 290.95}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 2}, 'wind': {'speed': 0.73, 'deg': 224, 'gust': 0.15}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-20 06:00:00'}, {'dt': 1787216400, 'main': {'temp': 295.47, 'feels_like': 295.64, 'temp_min': 295.47, 'temp_max': 295.47, 'pressure': 1017, 'sea_level': 1017, 'grnd_level': 1000, 'humidity': 72, 'temp_kf': 0, 'dew_point': 290.1}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 0}, 'wind': {'speed': 2.04, 'deg': 233, 'gust': 0.72}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-20 09:00:00'}, {'dt': 1787227200, 'main': {'temp': 298.35, 'feels_like': 298.52, 'temp_min': 298.35, 'temp_max': 298.35, 'pressure': 1016, 'sea_level': 1016, 'grnd_level': 1000, 'humidity': 61, 'temp_kf': 0, 'dew_point': 289.52}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 2}, 'wind': {'speed': 4.46, 'deg': 252, 'gust': 3.36}, 'visibility': 9552, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-20 12:00:00'}, {'dt': 1787238000, 'main': {'temp': 301.93, 'feels_like': 302.31, 'temp_min': 301.93, 'temp_max': 301.93, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 996, 'humidity': 48, 'temp_kf': 0, 'dew_point': 288.18}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02d'}], 'clouds': {'all': 14}, 'wind': {'speed': 7.21, 'deg': 303, 'gust': 8.3}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-20 15:00:00'}, {'dt': 1787248800, 'main': {'temp': 300.38, 'feels_like': 301, 'temp_min': 300.38, 'temp_max': 300.38, 'pressure': 1012, 'sea_level': 1012, 'grnd_level': 995, 'humidity': 53, 'temp_kf': 0, 'dew_point': 289.24}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 7}, 'wind': {'speed': 5.05, 'deg': 340, 'gust': 9.39}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-20 18:00:00'}, {'dt': 1787259600, 'main': {'temp': 295.39, 'feels_like': 295.58, 'temp_min': 295.39, 'temp_max': 295.39, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 998, 'humidity': 73, 'temp_kf': 0, 'dew_point': 290.62}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 1}, 'wind': {'speed': 4.2, 'deg': 120, 'gust': 3.04}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-20 21:00:00'}, {'dt': 1787270400, 'main': {'temp': 294.03, 'feels_like': 294.29, 'temp_min': 294.03, 'temp_max': 294.03, 'pressure': 1015, 'sea_level': 1015, 'grnd_level': 998, 'humidity': 81, 'temp_kf': 0, 'dew_point': 290.83}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 0}, 'wind': {'speed': 2.27, 'deg': 132, 'gust': 1.64}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-21 00:00:00'}, {'dt': 1787281200, 'main': {'temp': 292.99, 'feels_like': 293.3, 'temp_min': 292.99, 'temp_max': 292.99, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 997, 'humidity': 87, 'temp_kf': 0, 'dew_point': 291}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 0}, 'wind': {'speed': 1.56, 'deg': 158, 'gust': 1.56}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-21 03:00:00'}, {'dt': 1787292000, 'main': {'temp': 292.21, 'feels_like': 292.55, 'temp_min': 292.21, 'temp_max': 292.21, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 996, 'humidity': 91, 'temp_kf': 0, 'dew_point': 291.04}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 0}, 'wind': {'speed': 1.27, 'deg': 167, 'gust': 0.96}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-21 06:00:00'}, {'dt': 1787302800, 'main': {'temp': 294.71, 'feels_like': 294.93, 'temp_min': 294.71, 'temp_max': 294.71, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 997, 'humidity': 77, 'temp_kf': 0, 'dew_point': 290.47}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 0}, 'wind': {'speed': 2.31, 'deg': 190, 'gust': 0.9}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-21 09:00:00'}, {'dt': 1787313600, 'main': {'temp': 297.99, 'feels_like': 298.17, 'temp_min': 297.99, 'temp_max': 297.99, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 997, 'humidity': 63, 'temp_kf': 0, 'dew_point': 289.94}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 2}, 'wind': {'speed': 4.56, 'deg': 252, 'gust': 3.65}, 'visibility': 8998, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-21 12:00:00'}, {'dt': 1787324400, 'main': {'temp': 300.31, 'feels_like': 301.06, 'temp_min': 300.31, 'temp_max': 300.31, 'pressure': 1011, 'sea_level': 1011, 'grnd_level': 994, 'humidity': 55, 'temp_kf': 0, 'dew_point': 289.64}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02d'}], 'clouds': {'all': 11}, 'wind': {'speed': 5.57, 'deg': 300, 'gust': 6.8}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-21 15:00:00'}, {'dt': 1787335200, 'main': {'temp': 299.62, 'feels_like': 299.62, 'temp_min': 299.62, 'temp_max': 299.62, 'pressure': 1010, 'sea_level': 1010, 'grnd_level': 993, 'humidity': 58, 'temp_kf': 0, 'dew_point': 290.23}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 7}, 'wind': {'speed': 6.78, 'deg': 328, 'gust': 7.75}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-21 18:00:00'}, {'dt': 1787346000, 'main': {'temp': 295.09, 'feels_like': 295.38, 'temp_min': 295.09, 'temp_max': 295.09, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 996, 'humidity': 78, 'temp_kf': 0, 'dew_point': 291.16}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 0}, 'wind': {'speed': 4.01, 'deg': 96, 'gust': 4.45}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-21 21:00:00'}, {'dt': 1787356800, 'main': {'temp': 294.23, 'feels_like': 294.53, 'temp_min': 294.23, 'temp_max': 294.23, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 997, 'humidity': 82, 'temp_kf': 0, 'dew_point': 291.25}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 0}, 'wind': {'speed': 3.56, 'deg': 125, 'gust': 3.1}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-22 00:00:00'}, {'dt': 1787367600, 'main': {'temp': 293.32, 'feels_like': 293.69, 'temp_min': 293.32, 'temp_max': 293.32, 'pressure': 1012, 'sea_level': 1012, 'grnd_level': 995, 'humidity': 88, 'temp_kf': 0, 'dew_point': 291.46}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 5}, 'wind': {'speed': 1.55, 'deg': 140, 'gust': 1}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-22 03:00:00'}, {'dt': 1787378400, 'main': {'temp': 292.62, 'feels_like': 293.05, 'temp_min': 292.62, 'temp_max': 292.62, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 996, 'humidity': 93, 'temp_kf': 0, 'dew_point': 291.67}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 1}, 'wind': {'speed': 1.54, 'deg': 165, 'gust': 1.12}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-22 06:00:00'}, {'dt': 1787389200, 'main': {'temp': 294.39, 'feels_like': 294.74, 'temp_min': 294.39, 'temp_max': 294.39, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 997, 'humidity': 83, 'temp_kf': 0, 'dew_point': 291.58}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02d'}], 'clouds': {'all': 18}, 'wind': {'speed': 2.71, 'deg': 165, 'gust': 1.12}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-22 09:00:00'}, {'dt': 1787400000, 'main': {'temp': 297.12, 'feels_like': 297.43, 'temp_min': 297.12, 'temp_max': 297.12, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 997, 'humidity': 71, 'temp_kf': 0, 'dew_point': 291.32}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02d'}], 'clouds': {'all': 19}, 'wind': {'speed': 3.98, 'deg': 255, 'gust': 2.62}, 'visibility': 9627, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-22 12:00:00'}, {'dt': 1787410800, 'main': {'temp': 299.26, 'feels_like': 299.26, 'temp_min': 299.26, 'temp_max': 299.26, 'pressure': 1011, 'sea_level': 1011, 'grnd_level': 995, 'humidity': 57, 'temp_kf': 0, 'dew_point': 289.67}, 'weather': [{'id': 801, 'main': 'Clouds', 'description': 'few clouds', 'icon': '02d'}], 'clouds': {'all': 12}, 'wind': {'speed': 3.97, 'deg': 278, 'gust': 4.75}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-22 15:00:00'}, {'dt': 1787421600, 'main': {'temp': 298.27, 'feels_like': 298.35, 'temp_min': 298.27, 'temp_max': 298.27, 'pressure': 1011, 'sea_level': 1011, 'grnd_level': 995, 'humidity': 58, 'temp_kf': 0, 'dew_point': 289.29}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 6}, 'wind': {'speed': 1.32, 'deg': 301, 'gust': 3.71}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-22 18:00:00'}, {'dt': 1787432400, 'main': {'temp': 294, 'feels_like': 294.15, 'temp_min': 294, 'temp_max': 294, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 997, 'humidity': 77, 'temp_kf': 0, 'dew_point': 289.98}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 0}, 'wind': {'speed': 4.75, 'deg': 131, 'gust': 3.57}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-22 21:00:00'}, {'dt': 1787443200, 'main': {'temp': 292.59, 'feels_like': 292.76, 'temp_min': 292.59, 'temp_max': 292.59, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 998, 'humidity': 83, 'temp_kf': 0, 'dew_point': 289.91}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 0}, 'wind': {'speed': 4.45, 'deg': 113, 'gust': 4.91}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-23 00:00:00'}, {'dt': 1787454000, 'main': {'temp': 292.43, 'feels_like': 292.58, 'temp_min': 292.43, 'temp_max': 292.43, 'pressure': 1013, 'sea_level': 1013, 'grnd_level': 996, 'humidity': 83, 'temp_kf': 0, 'dew_point': 289.71}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 0}, 'wind': {'speed': 3.08, 'deg': 110, 'gust': 3.18}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-23 03:00:00'}, {'dt': 1787464800, 'main': {'temp': 291.91, 'feels_like': 292.09, 'temp_min': 291.91, 'temp_max': 291.91, 'pressure': 1014, 'sea_level': 1014, 'grnd_level': 997, 'humidity': 86, 'temp_kf': 0, 'dew_point': 289.85}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01n'}], 'clouds': {'all': 0}, 'wind': {'speed': 1.26, 'deg': 97, 'gust': 1.81}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'n'}, 'dt_txt': '2026-08-23 06:00:00'}, {'dt': 1787475600, 'main': {'temp': 293.9, 'feels_like': 294.02, 'temp_min': 293.9, 'temp_max': 293.9, 'pressure': 1015, 'sea_level': 1015, 'grnd_level': 999, 'humidity': 76, 'temp_kf': 0, 'dew_point': 289.73}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 0}, 'wind': {'speed': 1.16, 'deg': 215, 'gust': 1.51}, 'visibility': 10000, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-23 09:00:00'}, {'dt': 1787486400, 'main': {'temp': 295.64, 'feels_like': 295.72, 'temp_min': 295.64, 'temp_max': 295.64, 'pressure': 1015, 'sea_level': 1015, 'grnd_level': 999, 'humidity': 68, 'temp_kf': 0, 'dew_point': 289.04}, 'weather': [{'id': 800, 'main': 'Clear', 'description': 'clear sky', 'icon': '01d'}], 'clouds': {'all': 4}, 'wind': {'speed': 4.47, 'deg': 251, 'gust': 3.49}, 'visibility': 9224, 'pop': 0, 'sys': {'pod': 'd'}, 'dt_txt': '2026-08-23 12:00:00'}], 'city': {'id': 2561668, 'name': 'Agadir', 'coord': {'lat': 30.4202, 'lon': -9.5982}, 'country': 'MA', 'population': 698310, 'timezone': 3600, 'sunrise': 1787033220, 'sunset': 1787080673}}")