How do you add elements to a set with DataStax QueryBuilder? - cassandra

I have a table whose column types are
text, bigint, set<text>
I'm trying to update a single row and add an element to the set using QueryBuilder.
The code that overwrites the existing set looks like this (note this is scala):
val query = QueryBuilder.update("twitter", "tweets")
.`with`(QueryBuilder.set("sinceid", update.sinceID))
.and(QueryBuilder.set("tweets", setAsJavaSet(update.tweets)))
.where(QueryBuilder.eq("handle", update.handle))
I was able to find the actual CQL for adding an element to a set which is:
UPDATE users
SET emails = emails + {'fb#friendsofmordor.org'} WHERE user_id = 'frodo';
But could not find an example using QueryBuilder.
Based off of the CQL I also tried:
.and(QueryBuilder.set("tweets", "tweets"+{setAsJavaSet(update.tweets)}))
But it did not work. Thanks in advance

Use add (add one element at a time) or addAll (more than one any number of element at a time) method to add to a set.

To extend Ananth's answer:
QueryBuilder.add does not support BindMarker. To use BindMarker while adding in set, it is required to use QueryBuilder.addAll only.*
*Just a note, Collections.singleton may come in handy in this regard.

Using #Ananth and #sazzad answers, the code below works:
Session cassandraSession;
UUID uuid;
Long value;
Statement queryAddToSet = QueryBuilder
.update("tableName")
.with(QueryBuilder.addAll("setFieldName", QueryBuilder.bindMarker()))
.where(QueryBuilder.eq("whereFieldName", QueryBuilder.bindMarker()));
PreparedStatement preparedQuery = cassandraSession.prepare(queryAddToSet);
BoundStatement boundQuery = preparedQuery.bind();
boundQuery
.setUUID("whereFieldName", uuid)
.setSet("setFieldName", Collections.singleton(value));
session.execute(boundQuery);

Related

How Can I Sort These Many To Many Values Without a Through Table?

I am trying to compare the values in two manytomany fields...this almost works...
author_confirm = Author.objects.filter(id=self.object.update_reader_id).values_list('author_confirm').order_by('pk')
author = Author.objects.filter(id=self.object.update_reader_id).values_list('author').order_by('pk')
authors_are_equal = list(author) == list(author_confirm)
authors_are_not_equal = list(author) != list(author_confirm)
This works in that it gets me the values...but doesn't seem to be cooperating with the order_by...I currently have both fields with identical values...but their PKs are transposed so it tells me these fields are not identical...which is technically correct...but I see the problem is that the PKs are not listed in order...Is there a way to do this without a Through Table?
I am using UUIDs as the primary key....I'm not sure if this is relevant or not...but nonetheless I can't seem to get the values in an ordered way.
Thanks in advance for any ideas.
You should order by the author__pk and author_confirmed__pk, otherwise you are only ordering by the author object itself, which we lready know: that is the self.object.update_reader_id, hence the problem:
author_confirm = (
Author.objects.filter(id=self.object.update_reader_id)
.values_list('author_confirm')
.order_by('author_confirm__pk')
)
author = (
Author.objects.filter(id=self.object.update_reader_id)
.values_list('author')
.order_by('author__pk')
)

Want to know how to bind a map type column in a prepared insert statement in Cassandra with php drivers

Can someone please help me with the exact syntax to use prepared insert / update statements containing map type columns.
suppose :
UPDATE abc SET map = map + ? where id = ?
where map is the map type column,
I found an answer
Cassandra prepared statements with collections
but it just contained the syntax to generate a particular map type object rather binding.
You need to execute it as usual for prepared queries, but you need to pass Cassandra::Map object as first parameter, something like this:
$statement = $session->prepare('....')
$map = Cassandra\Type::map(Cassandra\Type::varchar(), Cassandra\Type::int())
->create('a', 1);
$id = 'something'
$session->execute($statement, array('arguments' => array($map, $id)));
You need to pass Map object because CQL's appending to the map expects another map as an argument.

Cassandra: no viable alternative at input 'IF'

This query:
UPDATE jdtestbysentence."sparseSupplement" SET uuid = 2b22da9c-58a6-11e8-ae82-2d3e941502e8 WHERE a_uid = "1849" IF EXISTS
gives this error:
no viable alternative at input 'IF' (...=
2b22da9c-58a6-11e8-ae82-2d3e941502e8 WHERE a_uid = ["184]9" IF...)
I am fairly new to Cassandra.
Can someone advise?
UPDATE jdtestbysentence."sparseSupplement"
SET uuid = 2b22da9c-58a6-11e8-ae82-2d3e941502e8 WHERE a_uid = "1849" IF EXISTS
Ok, so I created your table on my local like this:
CREATE TABLE "sparseSupplement" (uuid UUID, a_uid TEXT PRIMARY KEY);
I ran your CQL UPDATE, and sure enough I got the same error message. Essentially, there is some confusion around the use of quotes here. Double quotes are only to be used when enforcing case on a table or column name. When setting or checking the value of a TEXT (a_uid) you should use single quotes around 1849:
cassdba#cqlsh:stackoverflow> UPDATE "sparseSupplement"
SET uuid = 2b22da9c-58a6-11e8-ae82-2d3e941502e8
WHERE a_uid = '1849' IF EXISTS;
[applied]
-----------
False
Pro-tip: Also, I would caution you against using double-quotes like that. Unless you absolutely need it to match case to a Java class, it's just going to make it more difficult to work with that table. Kind of like it did here.
I have tried your query with some modification in my test environment and it worked.
UPDATE jdtestbysentence."sparseSupplement" SET uuid = 2b22da9c-58a6-11e8-ae82-2d3e941502e8 WHERE a_uid = '1849' IF EXISTS

Sorting DAM asset and Cq page based on last modified

I am trying to perform a freetext search on all the Cq:Page and dam:Asset with the ordering being the last modified.
I have created the Query for search which is as below:
1_group.p.or=true
1_group.1_type=cq:Page
1_group.2_type=dam:Asset
2_group.p.or=true
2_group.1_path=/content
2_group.2_path=/content/dam
fulltext=text
p.limit=-1
Now I need to sort the results based on last modified. But since cq:Page has property jcr:content/cq:lastModified and dam:Asset has property jcr:content/jcr:lastModified, I am unable to figure out which property should i use in the orderby field of predicate. Is there any way to form a predicate which uses different property values for pages and assets during sorting. Please let me know if we can achieve this in a single query.
Regards,
Shailesh
This can be done by creating a custom AbstractPredicateEvaluator and overriding the getOrderByComparator with your own comparator. Then you would register your custom predicate evaluator for your Query by calling registerPredicateEvaluator.
In the example below, you can use whatever you'd like for the customSort.sortby property. This can be useful if your comparator handles multiple types of sorting. You can get this information from the predicate via predicate.get("sortby").
QueryBuilder builder = resourceResolver.adaptTo(QueryBuilder.class);
Map<String, String> params = new HashMap<String, String>();
params.put("1_group", "true");
params.put("1_group.1_type", "cq:Page");
params.put("1_group.2_type", "dam:Asset");
params.put("2_group.p.or", "true");
params.put("2_group.1_path", "/content");
params.put("2_group.2_path", "/content/dam");
params.put("fulltext", text);
params.put("p.limit", "-1");
params.put("customSort.sortby", "last-modified");
PredicateGroup pg = PredicateGroup.create(params);
Query query = builder.createQuery(pg, resourceResolver.adaptTo(Session.class));
query.registerPredicateEvaluator("customSort", new CustomSortPredicateEvaluator());
SearchResult result = query.getResult();
there is no way since they are differenet type (cq:lastModified & jcr:lastModified), Even you use SQL2 like this (SELECT p.* FROM [nt:base] AS p WHERE ISDESCENDANTNODE(p, '/content') AND ( p.[jcr:primaryType]='dam:Asset' OR p.[jcr:primaryType]='cq:Page')) there no way to use ORDER BY.
Have to use Java code for sorting.
Keep your Query, get QueryResult to List and do Comparator Sort

Mapping Cassandra Super Columns

I guess everybody that played with Cassandra already read this article.
I trying to create my schema on CassandraCli, but I am having a lot of problems, can someone guide me to the right way? I am trying to create a similar structure like the Comments column family from the article.
In CassandraCli terminal I type:
create column family posts with column_type = ‘Super’ and comparator = ‘AsciiType’ and subcomparator = TimeUUIDType;
It works fine, there is no doc telling me that if I add a column_metadata attribute those will be for the super columns cause my column family is of type super, i can’t find if it is true so:
create column family posts with column_type = ‘Super’ and comparator = ‘AsciiType’ and subcomparator = ‘TimeUUIDType’ and column_metadata = [{column_name:'body'}];
I am trying to create the same as the comment column family of the article, but when i try to populate
set posts['post1'][timeuuid()][body] = ‘Hello I am Goku!’;
i got:
Invalid UUID string: body
I guess because i chose the subcomparator be of type timeuuid and the body is a string, it should be a timeuuid, so HOW my columns inside the super column which is the type timeuuid could holds columns with string type names as the comments of the article are created?
Thanks
I think you switched what comparator_type and subcomparator_type apply to. In super column families, comparator_type applies to the super column names, and subcombparator_type applies to the subcolumn names.
Switch the comparator types and your first example should work.
set posts[1][timeuuid()][utf8('body')] = 'Hello I am Goku!';
The correct answer shall be that.
:p
Did you try quoting 'body'?
set posts['post1'][timeuuid()]['body'] = ‘Hello I am Goku!’;
I tried:
set posts[1][timeuuid()]['body'] = 'Hello I am Goku!';
it worked...

Resources