Camel CQL Component - Query with multiple parameters - cassandra

I'm creating an Camel route that consumes data from Cassandra DB using CQL component and I want to pass multiple parameters to the where statement.
How can I pass multiple parameters to construct the prepared stratement internally?
I've checked in DOC and I found the way to pass one parameter:
rest("cassandra")
.get()
.route()
.routeId("teste")
.removeHeaders("Camel*")
.setHeader(Exchange.HTTP_METHOD, simple(HttpMethod.GET.name()))
.process(e-> e.getIn().setBody("Gabriel")
.to("cql://localhost:9042/teste?cql=SELECT * FROM teste_table where name = ? ALLOW FILTERING")
The way above works fine, but I want to pass more than one parameter.

After some retries, I found a way to do it, simply passing an object array in the exchange in body, see below:
import com.datastax.driver.core.LocalDate;
import com.datastax.driver.core.Row;
...
rest("cassandra")
.get()
.route()
.routeId("test-route")
.removeHeaders("Camel*")
.setHeader(Exchange.HTTP_METHOD, simple(HttpMethod.GET.name()))
.process(e-> e.getIn().setBody(new Object[] {"Gabriel", LocalDate.fromYearMonthDay(1994, 10, 25)}))
.to("cql://localhost:9042/teste?cql=SELECT * FROM teste_table where name = ? and date_of_birth= ? ALLOW FILTERING")
.process(e -> {
Row[] rows = e.getIn().getBody(Row[].class);
for (Row row : rows)
System.out.println("name: " + row.getString("name") + ", idade: " + row.getInt("idade"));
});

Related

M (PowerQuery), set the value of a non-primitive variable in a let statement

I'm writing a custom M Language (PowerQuery in Excel) function to query a RESTful interface. This interface has a large number of optional parameters.
Starting with a simple case- I handle an optional limit passed as a simple (primitive) value as follows-
/*
* RESTful API Get from the named endpoint
*/
(endpoint as text, optional limit) =>
let
// query limit
// If limit is supplied as a number, it will be converted to text
// If limit is not supplied it will be set to the value "1000"
limit = if limit <> null then Text.From(limit) else "1000",
As the full API has many paramaters I wanted to use a Record to pass them to the function, but then I realised I don't know how to persuade M to write the default values into the parameter record.
I tried a couple of options.
Direct access-
(endpoint as text, optional params as record) =>
let
params[limit] = if (params[limit] = null) then "1000",
the result is a syntax error-'Token equal expected'
Merging the new value of limit as a Record with "&"
(endpoint as text, optional params as record) =>
let
params = params & if params[limit] = null then [limit = "1000"] else [],
result syntax error-'Token Literal expected'
I'm clearly missing something about the syntax rules for let statements, I know I need a variable = value assignment, and it looks as if putting anything other than a plain variable name on the LHS to write elements inside a structured value is not allowed, but i'm not sure how to acieve this otherwise?
Not sure exactly what you want here, but to create a List of Records where some Records have a default parameter and others do not, you could try something like:
(newParams as record) =>
let
default = [limit=1000, param2=2, param3=3],
final = Record.Combine({default, newParams})
in
final
With regard to Record.Combine, the beauty is that the right hand record will override the left hand record if both are present; and it will just add to it if nothing is present.
So something like:
let
Source = [limit=400, param3="x", param7=246],
conv = fnParams(Source)
in
conv
=>
Depending on the required format of your output string, you can build it using List.Accumulate. eg:
let
Source = [limit=400, param3="x", param7=246],
conv = fnParams(Source),
list = List.Accumulate(List.Zip({Record.FieldNames(conv), Record.ToList(conv)}), "",
(state,current) =>state & "&" & current{0} & "=" & Text.From(current{1}) )
in
list
=> &limit=400&param2=2&param3=x&param7=246

How to bind variables inside collection literals in Cassandra 3.0 using java?

I have a java application in which I am parsing data and updating it to my Cassandra 3.0 database. I have been successful so far until it comes to my columns with user-defined types.
My attempt:
String statement_update = "UPDATE table SET "
+ "elements = elements + [{name: ? , associations: []}]"
+ " WHERE id = ?
elements is a user defined type in my Cassandra 3.0 Database.
It is composed of name (data type: text) and associations (data type: list).
PreparedStatement prepared_update = session.prepare(statement_update);
bound_update = prepared_update.bind(name, id);
variables name and id are of type String.
I have been trying to use a prepared statement to update my table with newly parsed data; however after the data is parsed I am having trouble adding more elements to my elements column. I get error: “Invalid list literal for elements: bind variables are not supported inside collection literals.” How do I work around or resolve this?
I have tried ways of changing the statement_update to “UPDATE table SET elements = elements + ? WHERE id = ?”, but I don’t know what kind of list (or even if its a list) to add to my bind statement.
What is needed to satisfy my user-defined type: elements?
Try another update notation:
session := getGocqlSession()
err := session.Query(
"UPDATE table SET mymapcolumn[?] = ? WHERE rowkey = ?",
mapKey, mapValue, rowKey,
).Exec()
This worked for me.
I have done this on Go, but maybe this approach will help.

Pass a list of string's in IN clause in DocumentDb Query

This query works when i try to fetch records using IN and multiple Email Id's:
var families = _client.CreateDocumentQuery<Restraunt>(_documentCollection.SelfLink,
"Select Restraunt.RestrauntId from Restraunt join Rest in Restraunt.Emails where Emails.Email IN ('abc#gmail.com','ab#gmail.com') ").AsEnumerable().ToList();
I want to know how can i pass a list of Email id's as a string in the query?
I tried passing the list of strings directly but is unable to resolve that. Is there any way out to do that?
Let's say i have
List<string> elist=new List<string>{"abc#gmail.com","b#gmail.com"}
How can i pass elist in the query?
You have to change your query to use ARRAY_CONTAINS instead, i.e. like this:
Select Restraunt.RestrauntId
from Restraunt
join Rest in Restraunt.Emails
where ARRAY_CONTAINS(['abc#gmail.com','ab#gmail.com'], Emails.Email)
Then you can parameterize that query, and send the array of emails as a parameter.
You can try this:
List<string> elist=new List<string>{"abc#gmail.com","b#gmail.com"};
string emails = string.Empty;
if (eList!= null)
{
emails = "'" + string.Join("','", eList.Select(x => x != String.Empty? x :"").Distinct().ToArray()) + "'";
emails = emails.Replace("','','", "','");
}
var families = _client.CreateDocumentQuery<Restraunt>(_documentCollection.SelfLink,
"Select Restraunt.RestrauntId FROM Restraunt join Rest in Restraunt.Emails
WHERE Emails.Email IN (" + emails + ") ").AsEnumerable().ToList();

ServiceStack SelectLazy<long> System.NullReferenceException

using (IDbConnection db = dbFactory.OpenDbConnection()) {
List<long> x = db.SelectLazy<long>(
"SELECT Id FROM MyTable").ToList();
}
Why is x null?
It works when I use Select instead of SelectLazy, or when I use SelectLazy on the entire row and not just the Id.
In OrmLite you use different API's to match the results you're after, e.g:
Select* API's for returning a List<MyTable>
Column* API's for returning a column of field values, e.g List<long>
Single* API's for returning a Single Row, e.g Table
Scalar* API's for returning a Single field value, e.g long
So to select a column as a List of fields you use db.Column, e.g:
var results = db.Column<long>(db.From<MyTable>().Select(x => x.Id));
These also have Raw Sql* equivalents, e.g:
var results = db.SqlColumn<long>("SELECT Id FROM MyTable");

Using DbContext.FindBy not with a PK

Objective:
I have a table called Publication that contains Id, RecordId, EntityType and a couple other columns. I select all the records that need to be published to another database from that table. I then loop that collection to process the records and move the records to the other db.
Background:
The EntityType column is used to Identify the Set that the context needs to retrieve. I also use reflection to create a object of that type to see if it implements a certain type of interface. If the record being processed does implement that interface then I know that the RecordId for that record in the Publication table is not a PK in the Set() but rather a FK.
this code works fine when I am going after the PK values for EntityTypes that do not inherit the specific interface.
object authoringRecordVersion = PublishingFactory.AuthoringContext.Set(recordType.Entity.GetType()).Find(record.RecordId);
Problem:
DbContext.Set(EntityType).Find(PK) goes after the PrimaryKey value. How can I tell Set() to search like this sudo code example since 'Where' is not allowed
object authoringRecordVersion = PublishingFactory.AuthoringContext.Set(recordType.Entity.GetType()).Where(c => c.HeaderRecordId == record.RecordId)
Update:
I am working on Implementing the following. Will advise results tomorrow
var sql = "SELECT * from " + record.Entity + " WHERE HeaderRecordId = '" + record.RecordId + "'";
authoringRecordVersion = PublishingFactory.AuthoringContext.Set(recordType.Entity.GetType()).SqlQuery(sql).AsNoTracking();
.SqlQuery(sql).AsNoTracking();
does work effectively. Don't know why I didn't see this earlier.

Resources