Question

I have a very simple table

cqlsh:hell> describe columnfamily info ;

CREATE TABLE info (
  nos int,
  value map<text, text>,
  PRIMARY KEY (nos)
) 

The following is the query where I am trying to update the value .

update info set value = {'count' : '0' , 'onget' :  'function onget(value,count) { count++ ; return {"value": value, "count":count} ; }' } where nos  <= 1000 ;
Bad Request: Invalid operator LTE for PRIMARY KEY part nos

I use any operator for specifying the constraint . It complains saying invalid operator. I am not sure what I am doing wrong in here , according to cassandra 3.0 cql doc, there are similar update queries.

The following is my version

[cqlsh 4.1.0 | Cassandra 2.0.3 | CQL spec 3.1.1 | Thrift protocol 19.38.0]

I have no idea , whats going wrong.

Was it helpful?

Solution

The answer is really in my comment, but it needs a bit of elaboration. To restate from the comment...

The first predicate of the where clause has to uniquely identify the partition key. In your case, since the primary key is only one column the partition key == the primary key.

Cassandra can't do range scans over partitions. In the language of CQL, a partition is a potentially wide storage row that is uniquely identified by a key. In this case, the values in your nos column. The values of the partition keys are hashed into tokens which explicitly identify where that data lives in the cluster. Since that hash has no order to it, Cassandra cannot use any operator other than equality to route a statement to the correct destination. This isn't a primary key index that could potentially be updated, it is the fundamental partitioning mechanism in Cassandra. So, you can't use inequality operators as the first clause of a predicate. You can use them in subsequent clauses because the partition has been identified and now you're dealing with an ordered set of columns.

OTHER TIPS

You can't use non-equal condition on the partition key (nos is your partition key).

http://cassandra.apache.org/doc/cql3/CQL.html#selectWhere

Cassandra currently does not support user defined functions inside a query such as the following.

update info set value = {'count' : '0' , 'onget' :  'function onget(value,count) { count++ ; return {"value": value, "count":count} ; }' } where nos  <= 1000 ;

First, can you push this onget function into the application layer? You can first query all the rows which nos < 1000. Then increment rows those via some batch query.

Otherwise, you can use a counter column for nos, not a int data type. Notice though, you cannot mix map data type with counter column families unless the non-counter columns are part of a composite key.

Also, you probably doe not want to have nos, a column that changes value as the primary key.

CREATE TABLE info (
  id UUID,
  value map<text, text>,
  PRIMARY KEY (id)
) 

CREATE TABLE nos_counter (
  info_id UUID,
  nos COUNTER,
  PRIMARY KEY (info_id)
) 

Now you can update the nos counter like this.

update info set nos = nos + 1 where info_id = 'SOME_UUID';
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top