Cassandra Collections

Collections allow a single column to hold multiple values. Instead of creating a separate table or joining data, you store a list of tags, a set of email addresses, or a map of key-value pairs directly inside one column. Cassandra supports three collection types: LIST, SET, and MAP.

The Shopping Bag Analogy

A regular column is like a single item you hand to a cashier — one value, one column. A collection column is like a shopping bag — one bag, multiple items inside. A LIST is a bag where the order of items matters and duplicates are allowed. A SET is a bag where every item is unique and order does not matter. A MAP is a bag of labeled envelopes — each envelope (key) contains one item (value).

Column Type   Duplicates?  Ordered?   Example
──────────────────────────────────────────────────────────────
LIST          Yes          Yes        ['milk','bread','milk']
SET           No           No         {'milk','bread','eggs'}
MAP           Keys unique  Keys sort  {'color':'red','size':'L'}

LIST

A LIST stores an ordered sequence of values. You can add items to the beginning or end, and the same value can appear more than once.

Create a Table with a LIST

CREATE TABLE playlists (
  playlist_id  UUID PRIMARY KEY,
  name         TEXT,
  songs        LIST<TEXT>
);

Insert Data into a LIST

INSERT INTO playlists (playlist_id, name, songs)
VALUES (
  uuid(),
  'Morning Drive',
  ['Sunrise Song', 'Road Trip Beat', 'Open Highway']
);

Add Items to a LIST

-- Append to the end:
UPDATE playlists SET songs = songs + ['Afternoon Chill']
WHERE playlist_id = [uuid];

-- Prepend to the beginning:
UPDATE playlists SET songs = ['Wake Up Tune'] + songs
WHERE playlist_id = [uuid];

Remove an Item by Index

-- Remove the item at index 0 (first item):
DELETE songs[0] FROM playlists WHERE playlist_id = [uuid];

Query a LIST Column

SELECT songs FROM playlists WHERE playlist_id = [uuid];

 songs
──────────────────────────────────────────────────
 ['Sunrise Song', 'Road Trip Beat', 'Open Highway']

SET

A SET stores unique, unordered values. Adding the same item twice has no effect — the set simply keeps one copy. Sets work well for tags, roles, permissions, and email addresses.

Create a Table with a SET

CREATE TABLE articles (
  article_id  UUID PRIMARY KEY,
  title       TEXT,
  tags        SET<TEXT>
);

Insert Data into a SET

INSERT INTO articles (article_id, title, tags)
VALUES (
  uuid(),
  'Cassandra for Beginners',
  {'database', 'nosql', 'cassandra', 'tutorial'}
);

Add Items to a SET

UPDATE articles SET tags = tags + {'distributed'}
WHERE article_id = [uuid];

Remove an Item from a SET

UPDATE articles SET tags = tags - {'tutorial'}
WHERE article_id = [uuid];

Query a SET Column

SELECT tags FROM articles WHERE article_id = [uuid];

 tags
────────────────────────────────────────────────────
 {'cassandra', 'database', 'distributed', 'nosql'}

Cassandra always returns SET values in sorted order regardless of the order you inserted them.

MAP

A MAP stores key-value pairs. Each key is unique within the map and maps to one value. Maps are ideal for attributes, configuration settings, and any situation where you need a labeled value store.

Create a Table with a MAP

CREATE TABLE user_preferences (
  user_id     UUID PRIMARY KEY,
  username    TEXT,
  settings    MAP<TEXT, TEXT>
);

Insert Data into a MAP

INSERT INTO user_preferences (user_id, username, settings)
VALUES (
  uuid(),
  'alice',
  {
    'theme': 'dark',
    'language': 'en',
    'timezone': 'UTC-5'
  }
);

Add or Update a MAP Entry

-- Add a new key:
UPDATE user_preferences SET settings['notifications'] = 'on'
WHERE user_id = [uuid];

-- Update an existing key:
UPDATE user_preferences SET settings['theme'] = 'light'
WHERE user_id = [uuid];

Remove a MAP Entry

DELETE settings['notifications']
FROM user_preferences
WHERE user_id = [uuid];

Query a MAP Column

SELECT settings FROM user_preferences WHERE user_id = [uuid];

 settings
──────────────────────────────────────────────────────────────
 {'language': 'en', 'theme': 'light', 'timezone': 'UTC-5'}

Frozen Collections

A frozen collection is serialized as a single blob instead of stored as individual cells. You cannot update individual elements of a frozen collection — you must replace the entire value. Frozen collections are required when nesting collections inside each other or using a collection as part of a primary key.

-- Frozen list — must replace the whole list to change it:
CREATE TABLE archived_logs (
  log_id   UUID PRIMARY KEY,
  messages FROZEN<LIST<TEXT>>
);

-- Nested collection (requires frozen):
CREATE TABLE config (
  config_id UUID PRIMARY KEY,
  data      MAP<TEXT, FROZEN<LIST<TEXT>>>
);

Collections in Primary Keys

You cannot use a non-frozen collection as a partition key or clustering column. Use FROZEN to make a collection eligible for use in a primary key.

When to Use Collections

Use Case                     Best Collection
──────────────────────────────────────────────────────────────
Ordered steps or queue        LIST
Tags, categories, permissions SET
Attributes, settings, labels  MAP

Collection Size Warning

Collections stored in a single column all live within one partition cell. Very large collections (thousands of items) create performance problems. The rule of thumb is to keep collections under a few hundred items. For larger, frequently queried datasets, model the data as a separate table with a proper primary key instead.

Summary

Cassandra collections — LIST, SET, and MAP — let you store multiple values in a single column without needing a separate table. LIST preserves order and allows duplicates, SET enforces uniqueness, and MAP pairs keys with values. Use FROZEN when nesting collections or when a collection appears in a primary key. Keep collections small; large collections belong in their own table.

Leave a Comment

Your email address will not be published. Required fields are marked *