How can I update a timeuuid column in Cassandra?
I tried the following query
cqlsh:mydb> UPDATE mytable SET mycolumn = '99b47d70-b465-11e9-8080-808080808080' WHERE mycolumn= '99a53b30-b465-11e9-8080-808080808080';
and it failed with message
InvalidRequest: Error from server: code=2200 [Invalid query] message="Invalid STRING constant (99b47d70-b465-11e9-8080-808080808080) for "mycolumn" of type timeuuid"
So I tried casting the constant values to timeuuid
cqlsh:mydb> UPDATE mytable SET mycolumn = cast('99b47d70-b465-11e9-8080-808080808080' as timeuuid) WHERE mycolumn= cast('99a53b30-b465-11e9-8080-808080808080' as timeuuid);
This time it failed with error
SyntaxException: line 1:34 no viable alternative at input '(' (UPDATE mytable SET mycolumn = cast
I saw the documentation on the cast function, and timeuuid is not listed under the output type for any other type.
https://docs.datastax.com/en/dse/5.1/cql/cql/cql_reference/refCqlFunction.html#refCqlFunction__cast
Does that mean a timeuuid column cannot be updated once created?
Update:
I came across the following information on the above page
UPDATE statements SET clause cannot be used to change PRIMARY KEY fields; therefore a new timeuuid can only be set if the target field is not part of the PRIMARY KEY field.
So, it is possible to update timeuuid columns. mycolumn is not part of the PRIMARY key.
Update 2:
Even the following command is failing with the same error no viable alternative at input
UPDATE website SET api_key = api_key WHERE 1;
So what is it that I am doing wrong?
I found the solution at Inserting a hard-coded UUID via CQLsh (Cassandra)
You shouldn't put the quotes around the UUID to stop it being interpreted as a string i.e.
There was no need to quote the uuid
Related
CREATE TABLE mykespace.newtable (
name text PRIMARY KEY,
marks int,
score float,
value float,
value2 blob
)
cqlsh:mykespace> alter table newtable alter value type int;
InvalidRequest: Error from server: code=2200 [Invalid query] message="Altering of types is not allowed"
cqlsh:mykespace> alter table newtable alter value2 type varint;
InvalidRequest: Error from server: code=2200 [Invalid query] message="Altering of types is not allowed"
unable to change data type , even int to varint , and float to int
As of Cassandra 3.10 and 3.0.11, the ability to change column data type has been removed with CASSANDRA-12443.
...because we no longer store the length for all types anymore, switching from a fixed-width to variable-width type causes issues. commitlog playback breaking startup, queries currently in flight getting back bad results, and special casing required to handle the changes.
The best workaround here, would be to drop the existing column, and create a new column with a different name (to avoid potential problems with commitlog replay). Something like:
ALTER TABLE mykeyspace.newtable DROP value;
ALTER TABLE mykeyspace.newtable ADD value_int int;
I have created this table:
CREATE TABLE postsbyuser(
userid bigint,
posttime timestamp,
postid uuid,
postcontent text,
year bigint,
PRIMARY KEY ((userid,year), posttime)
) WITH CLUSTERING ORDER BY (posttime DESC);
my Query is to get all user posts in one year ordered by desc posttime.
with the ordering is everything ok, but the problem is that the posttime will be changed if the user edits the postcontent:
update postsbyuser set postcontent='edited content' and posttime=edit_time where userid=id and year=year
I get the Error : [Invalid query] message="PRIMARY KEY part time found in SET part"
have you any idea how to order the posts with a changing time ?
It is not possible to update the value of any columns which are part of the PRIMARY KEY.
This error is returned:
[Invalid query] message="PRIMARY KEY part posttime found in SET part"
because you've included posttime in the SET part of your query and it is not allowed because it violates how the data is stored on disk. Cheers!
You should specify clustering column in your query.
update postsbyuser set postcontent='edited content' and posttime=edit_time where userid=id and year=year and posttime=previous_post_time
I'm new with cassandra and I met a problem. I created a keyspace demodb and a table users. This table got 3 columns: id (int and primary key), firstname (varchar), name (varchar).
this request send me the good result:
SELECT * FROM demodb.users WHERE id = 3;
but this one:
SELECT * FROM demodb.users WHERE firstname = 'francois';
doesn't work and I get the following error message:
InvalidRequest: code=2200 [Invalid query] message="No secondary indexes on the restricted columns support the provided operators: "
This request also doesn't work:
SELECT * FROM users WHERE firstname = 'francois' ORDER BY id DESC LIMIT 5;
InvalidRequest: code=2200 [Invalid query] message="ORDER BY with 2ndary indexes is not supported."
Thanks in advance.
This request also doesn't work:
That's because you are mis-understanding how sort order works in Cassandra. Instead of using a secondary index on firstname, create a table specifically for this query, like this:
CREATE TABLE usersByFirstName (
id int,
firstname text,
lastname text,
PRIMARY KEY (firstname,id));
This query should now work:
SELECT * FROM usersByFirstName WHERE firstname='francois'
ORDER BY id DESC LIMIT 5;
Note, that I have created a compound primary key on firstname and id. This will partition your data on firstname (allowing you to query by it), while also clustering your data by id. By default, your data will be clustered by id in ascending order. To alter this behavior, you can specify a CLUSTERING ORDER in your table creation statement:
WITH CLUSTERING ORDER BY (id DESC)
...and then you won't even need an ORDER BY clause.
I recently wrote an article on how clustering order works in Cassandra (We Shall Have Order). It explains this, and covers some ordering strategies as well.
There is one constraint in cassandra: any field you want to use in the where clause has to be the primary key of the table or there must be a secondary index on it. So you have to create an index to firstname and only after that you can use firstname in the where condition and you will get the result you were expecting.
I have a cassandra table defined like this:
CREATE TABLE test.test(
id text,
time bigint,
tag text,
mstatus boolean,
lonumb int,
PRIMARY KEY (id, time, tag)
)
And I want to select one column using select.
I tried:
select * from test where lonumb = 4231;
It gives:
code=2200 [Invalid query] message="No indexed columns present in by-columns clause with Equal operator"
Also I cannot do
select * from test where mstatus = true;
Doesn't cassandra support where as a part of CQL? How to correct this?
You can only use WHERE on the indexed or primary key columns. To correct your issue you will need to create an index.
CREATE INDEX iname
ON keyspacename.tablename(columname)
You can see more info here.
But you have to keep in mind that this query will have to run against all nodes in the cluster.
Alternatively you might rethink your table structure if the lonumb is something you'll do the most queries on.
Jny is correct in that WHERE is only valid on columns in the PRIMARY KEY, or those where a secondary index has been created for. One way to solve this issue is to create a specific query table for lonumb queries.
CREATE TABLE test.testbylonumb(
id text,
time bigint,
tag text,
mstatus boolean,
lonumb int,
PRIMARY KEY (lonumb, time, id)
)
Now, this query will work:
select * from testbylonumb where lonumb = 4231;
It will return all CQL rows where lonumb = 4231, sorted by time. I put id on the PRIMARY KEY to ensure uniqueness.
select * from test where mstatus = true;
This one is trickier. Indexes and keys on low-cardinality columns (like booleans) are generally considered a bad idea. See if there's another way you could model that. Otherwise, you could experiment with a secondary index on mstatus, but only use it when you specify a partition key (lonumb in this case), like this:
select * from testbylonumb where lonumb = 4231 AND mstatus = true;
Maybe that wouldn't perform too badly, as you are restricting it to a specific partition. But I definitely wouldn't ever do a SELECT * on mstatus.
I'm currently trying to model a column family that has two timestamps specifying whether an entry is valid (or 'active') at a given date (typically execution time).
No big issue with traditional SQL, 64 gigs of RAM and some indices, we're doing that quite often with our SQL server.
However, in CQL I haven't managed to model this scenario and write valid queries for it.
My basic model is (I skipped the PK definition!)
create table myTable(
id uuid,
validFrom timeuuid,
validTo timeuuid,
someInformationalData varChar
);
Some explanations:
due to the fact, that a validity date is not unique, I need a combined key in my final application this is going to be a usergroup reference (would be an ideal partition key)
validFrom/To are designed to be optional, but I could deal with by using boundary values (1970, 2038) for 'null' values passed through the persistence layer
I tried various combinations of partitioning/clustering keys, however neither of them resulted in valid CQL
-- only active results
select *
from
myTable
where
validFrom < now()
and
validTo > now()
I'm quite new to the NoSQL/CQL world and am struggling a bit with converting some of our applications. I could do it in memory, but I'm afraid, this could get a bottleneck at some point...
No sure if this kind of 'I have no idea what I'm doing' yell is appropriate, but any kind of help would be appreciated. :)
edit Here's one of the approaches I've been messing around with
drop table if exists myTable;
create table myTable(
id int,
datefrom timeuuid,
dateto timeuuid,
someColumns varChar,
primary key((id,datefrom),dateto)
);
create index if not exists my_idx on myTable(datefrom);
insert into myTable(id, datefrom,dateto,somecolumns)
values(0,minTimeuuid('1970-01-01 00:00:00'),minTimeuuid('2020-01-01 00:00:00'),'test');
insert into myTable(id,datefrom,dateto,somecolumns)
values(1,minTimeuuid('1970-01-01 00:00:00'),minTimeuuid('2012-01-01 00:00:00'),'test2');
select * from myTable where dateto > now() allow filtering;
-- invalid ("A column of a partition key can be restricted only if the preceding one is restricted by an Equal relation.")
select * from myTable where datefrom < now() and dateto > now() allow filtering;
The first query is limiting my result, the row with 'validTo=2012-01-01' is filtered, but I wasn't able to work out a scheme that worked on both limitations in the where clause.
If I understand your problem, what you are looking for is a way to run a range query based on the timestamp. Basically to be able to do this, your model will have to have the timestamp component as part of the clustering key:
create table myTable(
eventType uuid,
ts timestamp,
val text,
PRIMARY KEY (eventType, ts)
);
The above will allow you to run a query like: SELECT eventType, val from myTable where eventType = 'your_event' and ts >= 'start_ts' and ts < 'end_ts'.
What you need to remember is that the clustering keys are dictating the order on disk, thus making it possible to run efficiently queries like above. You can read more details about this in the CQL spec SELECT section.
Their is no such thing as Now() in cassandra like any other sql databases. you have to clearly mention today's date instead of Now() ..
You can use columns in which you defined as primary key or secondary index in where clause.