How can I make complex queries in Cassandra?
As example, I have a set of objects with id, name and others properties, and I want all Ids with the name starting with some string.
Is that possible?
Thanks,
Unfortunately, order preserving partition is not the ideal solution. What if you want to do range query base on some column value. Moreover, partitioning scheme selected applies to a whole Cassandra instance, and not individual keyspace.
You have to roll out your own index. Check my post on this topic
http://pkghosh.wordpress.com/2011/03/02/cassandra-secondary-index-patterns/
Pranab
yes, thats plausible. use range queries and order preserving partitioner. (read bens excellent slides about index and range queries)
Related
I have a table like this
CREATE TABLE my_table(
category text,
name text,
PRIMARY KEY((category), name)
) WITH CLUSTERING ORDER BY (name ASC);
I want to write a query that will sort by name through the entire table, not just each partition.
Is that possible? What would be the "Cassandra way" of writing that query?
I've read other answers in the StackOverflow site and some examples created single partition with one id (bucket) which was the primary key but I don't want that because I want to have my data spread across the nodes by category
Cassandra doesn't support sorting across partitions; it only supports sorting within partitions.
So what you could do is query each category separately and it would return the sorted names for each partition. Then you could do a merge of those sorted results in your client (which is much faster than a full sort).
Another way would be to use Spark to read the table into an RDD and sort it inside Spark.
Always model cassandra tables through the access patterns (relational db / cassandra fill different needs).
Up to Cassandra 2.X, one had to model new column families (tables) for each access pattern. So if your access pattern needs a specific column to be sorted then model a table with that column in the partition/clustering key. So the code will have to insert into both the master table and into the projection table. Note depending on your business logic this may be difficult to synchronise if there's concurrent update, especially if there's update to perform after a read on the projections.
With Cassandra 3.x, there is now materialized views, that will allow you to have a similar feature, but that will be handled internally by Cassandra. Not sure it may fit your problem as I didn't play too much with 3.X but that may be worth investigation.
More on materialized view on their blog.
I have a situation where I have a large partition/row with many cells/values. I need to query this row for all the cells sorted by a value (one of the keys). This sort value is dynamic, and changes of often. You can't update any of the primary keys of cassandra because it changes how the data is stored. So, how do I do this? Does cassandra not support normalized queries that the sort can change at any given moment?
Cassandra does not support normalized queries where the sort can change at any given moment. You can do sort on the client or using additional tools like Spark.
I have been unable to decipher on how to proceed with a use case....
I want to keep count of some items, and query the data such that
counter_value < threshold value
Now in cassandra, indexes cannot be made on counters, that is something that is a problem, is there a workaround modelling which can be done to accomplish something similar??
thanks
You have partially answered your own question, saying what you want to query. So lets say first model the data the way you will query it later.
If you want to query through counter value, it cannot be a counter type. As it doesn't complies the two conditions needed to query the data
Cannot be part of index
Cannot be part of the partition key
Counters are the most efficient way to do fast writes in Cassandra for a counter use of case. But unfortunately they cannot be part of where clause, because of above two restrictions.
So if you want to solve the problem using Cassandra, change the type to a long in Cassandra, make it the clustering key or make an index over that column. In any case this will slower your writes and increase the latency of every operation of updating counter value, as you will be using the anti parttern of read-before-write.
I would recommend to use the index.
Last but not least, I would consider using a SQL database for this problem.
Depending on what you're trying to return as a result, you might be able to do something with a user defined aggregate function. You can put arbitrary code in the user defined function to filter based on the value of the counter.
See some examples here and here.
Other approaches would be to filter the returned rows on the client side, or to load the data into Spark and filter the rows in Spark.
I've to test different datamodels for Cassandra. I'm thinking about to use a composite key made by key1:key2 for the row key.
With this configuration on Cassandra, for example, I can query to have all the rows having a specific key1 value and any key2 value but It's impossible otherwise (obtain all the rows having a specific key2's value and any key1).
Is it right?
thanks in advance
Cesare
If you use Order Preserving Partitioning (OPP), then yes, the keys will be stored sorted, and then you can get slices over a range of keys e.g. A:A to A:Z -- but not necessarily any:A to any:Z.
But, OPP is not guaranteed to evenly distribute the keys across the nodes and you could end up with "hot spots" of too many or too few keys. You probably want to use Random Partitioning (RP) which distributes the keys by storing by hash across all nodes.
However, since Columns are stored sorted, using Composite values can be pretty powerful for accessing ranges of data.
See this question for details on querying Composite columns using Hector .
If necessary, the column names could then be used as keys to do Multiget queries for additional lookups.
I hope these articles help you :)
http://pkghosh.wordpress.com/2011/03/02/cassandra-secondary-index-patterns/
http://www.datastax.com/docs/0.7/data_model/cfs_as_indexes
http://www.anuff.com/2011/02/indexing-in-cassandra.html
Also checkout this question
Storing a list of values in Cassandra
Here is an example use case:
You need to store last N (let's say 1000 as fixed bucket size) user actions with all details in timeuuid based columns.
Normally, each users' actions are already in "UserAction" column family where user id as row key, and actions in timeuuid columns. You may also have "AllActions" column family which stores all actions with same timeuuid as column name and user id as column value. It's basically a relationship column family but unfortunately without any details of user actions. Querying with this column family is expensive I guess, because of random partioner. On the other hand, if you store all details in "AllActions" CF then cassandra can't handle that big row properly at one point. This is why I want to store last N user actions with all details in fixed number of timeuuid based columns.
Maybe you may have a better design solution for this use case... I like to hear that ...
If not, the question is how to implement fixed number of (timeuuid) columns in cassandra (with CQL) effectively?
After insertion we could delete old (overflow) columns if we had some sort of range support in cql's DELETE. AFAIK there is no support for this.
So, any idea? Thanks in advance...
IMHO, this is something that C* must handle itself like compaction. It's not a good idea to handle this on client side.
Maybe, we need some configuration (storage) options for column families to make them suitable for "most recent data".