Build Cloud-Native apps with Apache Cassandra

GOT QUESTIONS from the Workshop? You're in the right place! Post a question here and we'll get you answers.

Click here for Week 7 Materials and Homework.

Registrations still open!


question

Shalini Ramachandra avatar image
Shalini Ramachandra asked ·

How is uniqueness maintained for sets/maps if Cassandra does not do a read-before-write?

[FOLLOW UP QUESTION TO #6283]

If read-before-write is not done for Sets / Maps, then how is the "uniqueness" maintained during a write?

collections
10 |1000 characters needed characters left characters exceeded

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

1 Answer

Erick Ramirez avatar image
Erick Ramirez answered ·

Cassandra does not need to read the contents of a set or map when updating the collection because the elements which already exist don't matter.

Sets

Let me illustrate it with a table containing friends:

CREATE TABLE friends_by_user (
    user text PRIMARY KEY,
    friends set<text>
)

It doesn't matter that I insert an unordered list of friends:

cqlsh> INSERT INTO friends_by_user (user, friends) VALUES ( 'erick', { 'tom', 'dick', 'harry', 'sally' } );

When I retrieve the data, it will be returned in lexical order:

cqlsh> SELECT * FROM friends_by_user WHERE user = 'erick';

 user  | friends
-------+-----------------------------------
 erick | {'dick', 'harry', 'sally', 'tom'}

By extension, adding a new element to the collection won't matter where it goes because there's no particular order:

cqlsh> UPDATE friends_by_user SET friends = friends + {'alice'} WHERE user = 'erick';

The order doesn't matter because it gets sorted when it is time to read the data:

cqlsh> SELECT * FROM friends_by_user WHERE user = 'erick';

 user  | friends
-------+--------------------------------------------
 erick | {'alice', 'dick', 'harry', 'sally', 'tom'}

And since a set collection only stores unique elements, adding Alice again won't make a difference:

cqlsh> UPDATE friends_by_user SET friends = friends + {'alice'} WHERE user = 'erick';
cqlsh> SELECT * FROM friends_by_user WHERE user = 'erick';

 user  | friends
-------+--------------------------------------------
 erick | {'alice', 'dick', 'harry', 'sally', 'tom'}

Maps

A map collection stores key-value pairs. The key is required to store and retrieve the corresponding value so by definition, the key is unique.

I'll use this table of addresses to illustrate:

CREATE TABLE addresses_by_user (
    user text PRIMARY KEY,
    addresses map<text, text>
)

Inserting Jack's home and work addresses:

cqlsh> INSERT INTO addresses_by_user (user,addresses) \
  VALUES ('jack', \
    {'home':'100 Main St', 'work': '1 5th Ave'} \
  );

we get:

cqlsh> SELECT * FROM addresses_by_user WHERE user = 'jack';

 user | addresses
------+----------------------------------------------
 jack | {'home': '100 Main St', 'work': '1 5th Ave'}

Adding another address isn't necessary for Cassandra to read what's already stored because it will get added as a new key-value pair:

cqlsh> UPDATE addresses_by_user \
  SET addresses = addresses + {'other':'300 Rodeo Dr'} \
  WHERE user = 'jack';

Updating the value of an existing address again doesn't require a read-before-write because C* just adds a new mutation to an existing key's value with a new write timestamp. In this example, we're updating the value of Jack's other address:

cqlsh> UPDATE addresses_by_user \
  SET addresses['other'] = '10 Downing St' \
  WHERE user = 'jack';

I hope this clarifies it for you. Cheers!

2 comments Share
10 |1000 characters needed characters left characters exceeded

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

Not a problem. Cheers!

0 Likes 0 · ·