CQL3 Each row to have its own schema

只愿长相守 提交于 2019-11-27 22:27:42

Older versions of Cassandra were Schema-less, meaning that you didn't have anywhere a definition of what a row could contain. What you need now could be partially done with a Map on Cassandra 2.1

CREATE TABLE toys (
    id text PRIMARY KEY,
    toy map<text, text>
)

Put some data ...

INSERT INTO toys (id, toy) VALUES ( '1', {'name':'Car', 'number_of_doors':'4', 'likes':'3'});
INSERT INTO toys (id, toy) VALUES ( '2', {'type':'Plane', 'flying_range':'100m'});
INSERT INTO toys (id, toy) VALUES ( '3', {'category':'Train', 'number_of_carriages':'10'});

Table content ...

 id | toy
----+-------------------------------------------------------
  3 |    {'category': 'Train', 'number_of_carriages': '10'}
  2 |             {'flying_range': '100m', 'type': 'Plane'}
  1 | {'likes': '3', 'name': 'Car', 'number_of_doors': '4'}

We can now create an index on keys ...

CREATE INDEX toy_idx ON toys (KEYS(toy));

... and perform queries on Map keys ...

SELECT * FROM toys WHERE toy CONTAINS KEY 'name';

 id | toy
----+-------------------------------------------------------
  1 | {'likes': '3', 'name': 'Car', 'number_of_doors': '4'}

Now you can update or delete map entries like you would do with normal columns, without reading before writing

DELETE toy['name'] FROM toys WHERE id='1';
UPDATE toys set toy = toy + {'name': 'anewcar'} WHERE id = '1';
SELECT * FROM toys;

 id | toy
----+-----------------------------------------------------------
  3 |        {'category': 'Train', 'number_of_carriages': '10'}
  2 |                 {'flying_range': '100m', 'type': 'Plane'}
  1 | {'likes': '3', 'name': 'anewcar', 'number_of_doors': '4'}

A few limitations

  1. you can not retrieve part of a collection: even if internally each entry of a map is stored as a column you can only retrieve the whole collection
  2. you have to choose whether creating an index on keys or on values, both simultaneously are not supported.
  3. since maps are typed you can't put mixed values -- in my examples all integers are now strings

I personally consider an extensive usage of this approach an anti-pattern.

HTH, Carlo

To add to Carlo's answer:

  1. Indexes on collections are not available on older cassandra versions (pre 2.1). Secondary indices have limitations as well, and are eventually consistent. Dig deeper into this.
  2. Don't go looking for "give me all toys that are cars" type queries with this. As with most things cassandra, think of how you're going to access the data (queries) and model accordingly. Depending on queries, it's perfectly acceptable to have multiple tables storing toy data with different structures to facilitate different queries.
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!