How to get inserted row immediately after query execution in cassandra? - node.js

I am trying to get last inserted row in cassandra but I am getting undefined
Here is how code looks for insert:
const cassandra = require('cassandra-driver');
const client = new cassandra.Client({ contactPoints: ['h1', 'h2'], keyspace: 'ks1' });
let query = "INSERT INTO users (id, name, email ) values (uuid(), ?, ?)";
client.execute(query, [ 'badis', 'badis#badis.com' ])
.then(result => console.log('User with id %s', result.rows[0].id));

Remember you are dealing with NoSQL ("non relational")
If I were to run a SELECT * FROM users LIMIT 1 on this table, my
result set would contain a single row. That row would be the one
containing the lowest hashed value of username (my partition key),
because that's how Cassandra stores data in the cluster. I would have
no way of knowing if it was the last one added or not, so this
wouldn't be terribly useful to you.
The workings are very different from those that you might be used to in MySQL.
If obtaining the last inserted row's information is needed for your system, then you will have to know it before you insert it.
Generating UUID
const Uuid = require('cassandra-driver').types.Uuid;
const id = Uuid.random();
Then you can use the id as another value for the prepared insert query
const cassandra = require('cassandra-driver');
const client = new cassandra.Client({ contactPoints: ['h1', 'h2'], keyspace: 'ks1' });
let query = "INSERT INTO users (id, name, email ) values (?, ?, ?)";
client.execute(query, [id, 'badis', 'badis#badis.com' ])
.then(result => console.log('User with id %s', id));

Related

ResponseError: Keyspace 'ks1' does not exist

I am new in Cassandra and just installed and wanted to try it. So I tried the following code:
import cassandra from 'cassandra-driver';
const client = new cassandra.Client({
contactPoints: ['localhost'],
localDataCenter: 'datacenter1',
keyspace: 'ks1'
});
const query1 = "CREATE TABLE users(name text , emailtext, PRIMARY_KEY(email, name)) VALUES('someone' , 's#s.com')";
const query2 = 'SELECT name, email FROM users WHERE name = ?';
await client.execute(query1);
await client.execute(query2)
.then(result => console.log('User with email %s', result.rows[0].email));
But I get this result:
> cassandra_test#1.0.0 start
> ts-node-esm src/index.ts
/home/a/bars/cassandra_test/node_modules/cassandra-driver/lib/readers.js:389
const err = new errors.ResponseError(code, message);
^
ResponseError: Keyspace 'ks1' does not exist
at FrameReader.readError (/home/a/bars/cassandra_test/node_modules/cassandra-driver/lib/readers.js:389:17)
at Parser.parseBody (/home/a/bars/cassandra_test/node_modules/cassandra-driver/lib/streams.js:209:66)
at Parser._transform (/home/a/bars/cassandra_test/node_modules/cassandra-driver/lib/streams.js:152:10)
at Parser.Transform._write (node:internal/streams/transform:175:8)
at writeOrBuffer (node:internal/streams/writable:392:12)
at _write (node:internal/streams/writable:333:10)
at Parser.Writable.write (node:internal/streams/writable:337:10)
at Protocol.ondata (node:internal/streams/readable:766:22)
at Protocol.emit (node:events:513:28)
at Protocol.emit (node:domain:489:12) {
info: 'Represents an error message from the server',
code: 8704
}
What is the problem and how can I fix it
PS: I use Ubuntu 22.04 and NodeJS version 9.
EDIT: I tried to create the KEYSPACE then edited my code like following:
import cassandra from 'cassandra-driver';
const client = new cassandra.Client({
contactPoints: ['localhost'],
localDataCenter: 'datacenter1',
keyspace: 'ks1'
});
const query0 = "CREATE TABLE users(name text, email text, PRIMARY_KEY(email, name))";
const query1 = "INSERT INTO users(name, email) VALUES ('someone' , 's#s.com')";
const query2 = "SELECT name, email FROM users WHERE name = someone";
await client.execute(query0 );
await client.execute(query1);
await client.execute(query2)
.then(result => console.log('User with email %s', result.rows[0].email));
But still get another error:
> cassandra_test#1.0.0 start
> ts-node-esm src/index.ts
/home/a/bars/cassandra_test/node_modules/cassandra-driver/lib/readers.js:389
const err = new errors.ResponseError(code, message);
^
ResponseError: line 1:53 no viable alternative at input '(' (... text, email text, PRIMARY_KEY[(]...)
at FrameReader.readError (/home/a/bars/cassandra_test/node_modules/cassandra-driver/lib/readers.js:389:17)
at Parser.parseBody (/home/a/bars/cassandra_test/node_modules/cassandra-driver/lib/streams.js:209:66)
at Parser._transform (/home/a/bars/cassandra_test/node_modules/cassandra-driver/lib/streams.js:152:10)
at Parser.Transform._write (node:internal/streams/transform:175:8)
at writeOrBuffer (node:internal/streams/writable:392:12)
at _write (node:internal/streams/writable:333:10)
at Parser.Writable.write (node:internal/streams/writable:337:10)
at Protocol.ondata (node:internal/streams/readable:766:22)
at Protocol.emit (node:events:513:28)
at Protocol.emit (node:domain:489:12) {
info: 'Represents an error message from the server',
code: 8192,
coordinator: '127.0.0.1:9042',
query: 'CREATE TABLE users(name text, email text, PRIMARY_KEY(email, name))'
}
I don't know what is the problem with the new error?
So the ks1 keyspace doesn't exist. You'll need to create it.
You can use the cqlsh tool (found in Cassandra's bin/ directory) for this.
As it looks like your cluster is a single, local node and doesn't have security active, you should be able to get into it simply by doing this:
$ bin/cqlsh
Once inside, you can create the keyspace with this command:
CREATE KEYSPACE ks1 WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 1};
That's the quickest way to solve this.
EDIT
After looking at the CQL queries, there are some errors up there, as well. A CREATE TABLE statement will not allow values to be inserted at creation time. So those will need to be two, separate queries:
const query1 = "CREATE TABLE users(name text , email text, PRIMARY KEY(email, name))"
const query1b = "INSERT INTO users (name,email) VALUES('someone' , 's#s.com')";
await client.execute(query1);
await client.execute(query1b);
Note that in the CREATE TABLE statement, I've also corrected the spacing between email text and PRIMARY KEY.
Also, query2 looks like it is using a question mark ? to bind a variable in a prepared statement. But I don't see where that's happening. When you get this point, have a look at the DataStax documentation for the Node.js driver on Parameterized Queries.
Also note that with the way this table's PRIMARY KEY is structured, it can only be queried by email or email and name. But it cannot be queried by name alone.
Thank you! Is there a way that I can also create the KEYSPACE using NodeJS instead of cqlsh?
So the short answer is "I don't recommend that."
The long answer is that Cassandra replicates schema out to each node, and programatic schema changes can be susceptible to network issues. That being said, as the keyspace is a part of your connection properites, it will probably fail before you have a chance to run the CREATE KEYSPACE statement.

How to update in node.js with sqlite3 like the function findByIdAndUpdate on mongo?

I want to do something like this:
async update(request, response){
const { id } = request.params;
const ovos = await connection('ovos').where('id', id);
const ovo = await ovos.findByIdAndUpdate(request.params.id, request.body, {new: true});
return ovo;
}
In a aplication with sqlite 3. I think it's clear what i want to do: Basicaly i want make a update funcion that select the table that i want to update by id and update them. whit new values give by the user.
the data in the 'ovos' table are: id; lote_id; id_gema; id_albumen; id_casca being (lote_id; id_gema; id_albumen; id_casca) foreig keys.
Assuming this is always an update rather than an upsert, you can just UPDATE like this:
let data = [lote_id, id_gema, id_albumen, id_casca, id];
let sql = `UPDATE ovos
SET lote_id = ?,
id_gema = ?,
id_albumen = ?,
id_casca = ?
WHERE id = ?`;
db.run(sql, data, function(err) {
if (err) {
return console.error(err.message);
}
console.log(`Rows updated: ${this.changes}`); // should be 1
});
Use the ? placeholders with the data in an array to avoid SQL injection - note the order of the array is important, so you may need to rearrange the way your request.params are structured.

How to join table that contains no data yet with sqlite

I am trying to join two tables: users and favourites. There is a possibility that a user has no favourites yet and when I tried to INNER JOIN the two I didn't get back the user without any favourites. Is there any way to join even if the second table has no data for that user?
I created the users tabel with the following code:
db.run(`CREATE TABLE Users(
UserId INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
Name TEXT NOT NULL,
Password TEXT NOT NULL,
Phone VARCHAR,
Email TEXT,
RestaurantId INTEGER,
FOREIGN KEY(RestaurantId) REFERENCES Restaurants(RestaurantId))`, (err) => {
if(err) {
console.error(err.message);
} else {
//insert some values
var insert = 'INSERT INTO Users (Name, Password, Phone, Email, RestaurantId) VALUES (?, ?, ?, ?, ?)';
db.run(insert, [
'Liam',
'blabla',
'+32412345678',
'email#email.com',
1
]);
}
}
);
And the favourites table with:
db.run(`CREATE TABLE Favourites(
FavouriteId INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
UserId INTEGER NOT NULL,
RestaurantId INTEGER NOT NULL,
FOREIGN KEY(UserId) REFERENCES Users(UserId),
FOREIGN KEY(RestaurantId) REFERENCES Restaurants(RestaurantId))`, (err) => {
if(err) {
console.error(err.message);
} else {
//insert some values
var insert = 'INSERT INTO Favourites (UserId, RestaurantId) VALUES (?, ?)';
db.run(insert, [
1,
1
]);
}
}
);
There is no problem with the data that exists in the table that was generated after these inserts. The problem only exists when a new user without favourites gets added to the database.
You are looking for LEFT JOIN. Take a look at the documentation: https://www.w3resource.com/sqlite/sqlite-left-join.php.
LEFT JOIN returns all the records on the left side of the join, with the matched records from the right side.

Inserting timestamp into Cassandra

I have a table created as follows:
CREATE TABLE my_table (
date text,
id text,
time timestamp,
value text,
PRIMARY KEY (id));
CREATE INDEX recordings_date_ci ON recordings (date);
I'm able to simply add a new row to the table using the following Node code:
const cassandra = require('cassandra-driver');
const client = new cassandra.Client({ contactPoints: ['localhost'], keyspace: 'my_keyspace'});
const query = 'INSERT INTO my_table (date, id, time, url) VALUES (?, ?, ?, ?)';
client.execute(query, ['20160901', '0000000000', '2016-09-01 00:00:00+0000', 'random url'], function(err, result) {
if (err){
console.log(err);
}
console.log('Insert row ended:' + result);
});
However, I get the following error:
'Error: Expected 8 or 0 byte long for date (24)
When I change the timestamp to epoc time:
client.execute(query, ['20160901', '0000000000', 1472688000, 'random url']
I get:
d
OverflowError: normalized days too large to fit in a C int
I'm able to insert new rows via cqlsh so I'm probably missing something with the node.js driver.
Any idea?
Thanks
Where you have a string 2016-09-01 00:00:00+0000, instead use new Date('2016-09-01 00:00:00+0000').

Cassandra - NodeJS - Issue while retrieving map type values

I am using helenus in my node-js project to get/set values in cassandra. I have a MapType field inside my Table, but when I retrieve the value from the table, I get an empty key-value set.
Below is the schema for my table
CREATE TABLE datapoints (
id uuid PRIMARY KEY,
created_at timestamp,
properties map<text,text>
);
I have inserted the values from cql using the query below
INSERT INTO datapoints (id, properties) VALUES (24053e20-63e9-11e3-8d81-0002a5d5c51b, { 'fruit' : 'apple', 'band' : 'Beatles' });
Below is my nodejs code:
var helenus = require('/usr/local/lib/node_modules/helenus')
var pool = new helenus.ConnectionPool({
hosts : ['localhost:9160'],
keyspace : 'mykeyspace',
timeout : 3000
});
pool.connect(function(err, keyspace){
if(err){
console.log("connect me error")
throw(err);
} else {
pool.cql("SELECT * FROM datapoints", [], function(err,results){
console.log("results", results)
results.forEach(function(row){
props = row.get('properties').value;
var id = row.get('id').value;
console.log("properties", props);
console.log("id", id);
});
})
}
});
The line console.log("properties", props); returns me a function, and when I call that function, I get an empty key value set. Please help.
It seems there was an issue with the deserialization of the collection types. The pull request that was made in the past broke the deserialization. I just pushed a fix to version 0.6.8 that should take care of this.

Resources