INSERT INTO testtable (id, user_name, gender, rank) VALUES (now(), 'test_user', 'MALE', 2) ;
Bad Request: line 1:60 no viable alternative at input 'now'
Can someone help on the above error message when trying to insert a timeuuid into a table in cassandra.
You need to upgrade Cassandra - the timeuuid functions were added in Cassandra 1.2.2.
Related
My table schema is:
CREATE TABLE users
(user_id BIGINT PRIMARY KEY,
user_name text,
email_ text);
I inserted below rows into the table.
INSERT INTO users(user_id, email_, user_name)
VALUES(1, 'abc#test.com', 'ABC');
INSERT INTO users(user_id, email_, user_name)
VALUES(2, 'abc#test.com', 'ZYX ABC');
INSERT INTO users(user_id, email_, user_name)
VALUES(3, 'abc#test.com', 'Test ABC');
INSERT INTO users(user_id, email_, user_name)
VALUES(4, 'abc#test.com', 'C ABC');
For searching data into the user_name column, I created an index to use the LIKE operator with '%%':
CREATE CUSTOM INDEX idx_users_user_name ON users (user_name)
USING 'org.apache.cassandra.index.sasi.SASIIndex'
WITH OPTIONS = {
'mode': 'CONTAINS',
'analyzer_class': 'org.apache.cassandra.index.sasi.analyzer.NonTokenizingAnalyzer',
'case_sensitive': 'false'};
Problem:1
When I am executing below Query, it returns 3 records only, instead of 4.
select *
from users
where user_name like '%ABC%';
Problem:2
When I use below query, it gives an error as
ERROR: com.datastax.driver.core.exceptions.InvalidQueryException:
ORDER BY with 2ndary indexes is not supported.
Query =select * from users where user_name like '%ABC%' ORDER BY user_name ASC;
Query:
select *
from users
where user_name like '%ABC%'
ORDER BY user_name ASC;
My requirement is to filter the user_name with order by user_name.
The first query does work correctly for me using cassandra:latest which is now cassandra:3.11.3. You might want to double-check the inserted data (or just recreate from scratch using the cql statements you provided).
The second one gives you enough info - ordering by secondary indexes is not possible in Cassandra. You might have to sort the result set in your application.
That being said I would not recommend running this setup in real apps. With some additional scale (when you have many records) this will be a suicide performance-wise. I should not go into much detail since maybe you already understand this and SO is not a wikia/documentation site, so here is a link.
As a Cassandra novice, I have a CQL design question. I want to re-use a concept which I've build before using RDBMS systems, to create history for customerData. The customer himself will only see the latest version, so that should be the fastest, but queries on whole history can be performed.
My suggested entity properties:
customerId text,
validFromDate date,
validUntilDate date,
customerData text
First save of customerData just INSERTs customerData with validFromDate=NOW and validUntilDate=31-12-9999
Subsequent saves of customerData changes the last record - setting validUntilDate=NOW - and INSERT new customerData with validFromDate=NOW and validUntilDate=31-12-9999
Result:
This way a query of (customerId, validUntilDate)=(id,31-12-9999) will give last saved version.
Query on (customerId) will give all history.
To query customerData at certain time t just use query with validFromDate < t < validUntilDate
My guess is PARTITION_KEY = customerId and CLUSTER_KEY can be validFromDate. Or use PRIMARY KEY = customerId. Or I could create two tables, one for fast querying of lastest version (has no history), and another for historical analyses.
How do you design this in CQL-way? I think I'm thinking too much RDBMish.
Use change timestamp as CLUSTERING KEY with DESC order, e.g
CREATE TABLE customer_data_versions (
id text,
change_time timestamp,
name text,
PRIMARY KEY (id, change_time)
) WITH CLUSTERING ORDER BY ( change_time DESC );
It will allow you to store data versions per customer id in descending order.
Insert two versions for the same id:
INSERT INTO customer_data_versions (id, change_time, name) VALUES ('id1', totimestamp(now()),'John');
INSERT INTO customer_data_versions (id, change_time, name) VALUES ('id1', totimestamp(now()),'John Doe');
Get last saved version:
SELECT * FROM customer_data_versions WHERE id='id1' LIMIT 1;
Get all versions for the id:
SELECT * FROM customer_data_versions WHERE id='id1';
Get versions between dates:
SELECT * FROM customer_data_versions WHERE id='id1' AND change_time <= before_date AND change_time >= after_date;
Please note, there are some limits for partition size (how much versions you will be able to store per customer id):
Cells in a partition: ~2 billion (231); single column value size: 2 GB ( 1 MB is recommended)
Cassandra docs and blog says that batches with conditional update statements work at the granularity of the partition, and partition is defined by first key in primary key
So, I have following keyspaces:
CREATE TABLE SOCIAL_PROFILE (
soc_net_type text,
soc_net_user_id text,
user_prof_id text,
PRIMARY KEY (soc_net_type, soc_net_user_id));
CREATE TABLE SOCIAL_PROFILE_CONTACT (
soc_prof_soc_net_type text,
soc_prof_soc_net_user_id text,
soc_net_user_id text,
PRIMARY KEY (soc_prof_soc_net_type, soc_prof_soc_net_user_id, soc_net_user_id));
And insert statement:
BEGIN BATCH
INSERT INTO social_profile (soc_net_type, soc_net_user_id, user_prof_id) VALUES ('vk', '1', '100') IF NOT EXISTS;
INSERT INTO social_profile_contact (soc_prof_soc_net_type, soc_prof_soc_net_user_id, soc_net_user_id) VALUES ('vk', '1', '2');
INSERT INTO social_profile_contact (soc_prof_soc_net_type, soc_prof_soc_net_user_id, soc_net_user_id) VALUES ('vk', '1', '3');
INSERT INTO social_profile_contact (soc_prof_soc_net_type, soc_prof_soc_net_user_id, soc_net_user_id) VALUES ('vk', '1', '4');
APPLY BATCH;
And social_profile_contact.soc_prof_soc_net_type = social_profile.soc_net_type they are both have same values and should be in the same partition, but Cassandra throws:
Bad Request: Batch with conditions cannot span multiple tables
I haven't found a word about tables in docs, what I'm doing wrong?
cqlsh 4.1.1 | Cassandra 2.0.11 | CQL spec 3.1.1 | Thrift protocol 19.39.0
"Batch with conditions cannot span multiple tables"
Two different column families (tables) using the same primary key are still two different partitions.
You need to move the statement with IF NOT EXISTS in the independent batch.
INSERT INTO social_profile (soc_net_type, soc_net_user_id, user_prof_id) VALUES ('vk', '1', '100') IF NOT EXISTS;
The batch insert with conditionals IF NOT EXISTS could contain only single type.
I have just started with Cassandra, created a simple ColumnFamily and some data using command given on Getting started on Cassandra download page, by executing below queries.
CREATE TABLE users (
user_id int PRIMARY KEY,
fname text,
lname text
);
INSERT INTO users (user_id, fname, lname)
VALUES (1745, 'john', 'smith');
INSERT INTO users (user_id, fname, lname)
VALUES (1744, 'john', 'doe');
INSERT INTO users (user_id, fname, lname)
VALUES (1746, 'john', 'smith');
My Hector code for fetching data:
RangeSlicesQuery<String, String, String> rangeSlicesQuery
= HFactory.createRangeSlicesQuery(keyspace, STR, STR, STR);
rangeSlicesQuery.setColumnFamily(columnFamily)
.setColumnNames(" fname ", " lname ")
.setKeys("6", "5")
.setRowCount(row_count);
QueryResult<OrderedRows<String, String, String>> result = rangeSlicesQuery.execute();
But when i fetch data using Hector API from Cassandra in Column name it contain blank space like column name fname will be: ' fname '.
And for my queries from Java Hector API i need to use same column name with blank space to fetch or save data.
Anybody have any idea, what i have done wrong, or what do i do to remove those trailing space.
Thanks
This issue has been fixed by using "WITH COMPACT STORAGE" when creating column families.
Discussion is here.
Instead of Hector i used Cassandra Java Driver pointed by Allan Elder, and my problem for trailing space in column name has been solved.
Doc for how to using Cassandra Java Driver is here and jars will be found by this project.
Thanks
I have one column in the cassandra keyspace that is of type timeuuid. When I try to insert a reocord from the java code (using DataStax java driver1.0.3). I get the following exception
com.datastax.driver.core.exceptions.InvalidQueryException: Invalid version for TimeUUID type.
at com.datastax.driver.core.exceptions.InvalidQueryException.copy(InvalidQueryException.java:35)
at com.datastax.driver.core.ResultSetFuture.extractCauseFromExecutionException(ResultSetFuture.java:269)
at com.datastax.driver.core.ResultSetFuture.getUninterruptibly(ResultSetFuture.java:183)
at com.datastax.driver.core.Session.execute(Session.java:111)
Here is my sample code:
PreparedStatement statement = session.prepare("INSERT INTO keyspace:table " +
"(id, subscriber_id, transaction_id) VALUES (now(), ?, ?);");
BoundStatement boundStatement = new BoundStatement(statement);
Session.execute(boundStatement.bind(UUID.fromString(requestData.getsubscriberId()),
requestData.getTxnId()));
I have also tried to use UUIDs.timeBased() instead of now(). But I am gettting the same exception.
Any help on how to insert/read from timeuuid datatype would be appreciated.
By mistake I had created
id uuid
That is why when I try to insert timeuuid in the uuid type field I was getting that exception.
Now I have changed the type for id to timeuuid and everything is working fine.