Search code examples
node.jstypescriptcassandra

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' , '[email protected]')";
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:

> [email protected] 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' , '[email protected]')";
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:

> [email protected] 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?


Solution

  • 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' , '[email protected]')";
    
    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.