Usage Tutorial

Auto-Load Models from a Directory

var models = require('express-cassandra');

//Tell express-cassandra to use the models-directory, and
//use bind() to load the models using cassandra configurations.
models.setDirectory( __dirname + '/models').bind(
    {
        clientOptions: {
            contactPoints: ['127.0.0.1'],
            protocolOptions: { port: 9042 },
            keyspace: 'mykeyspace',
            queryOptions: {consistency: models.consistencies.one}
        },
        ormOptions: {
            //If your keyspace doesn't exist it will be created automatically
            //using the default replication strategy provided here.
            defaultReplicationStrategy : {
                class: 'SimpleStrategy',
                replication_factor: 1
            },
            migration: 'safe',
            createKeyspace: true
        }
    },
    function(err) {
        if(err) console.log(err.message);
        else console.log(models.timeuuid());
    }
);

Automatic migration is supported. When your model schema changes, the config variable migration defines the migration behaviour.

  • alter will try to alter the corresponding cassandra table to match the new schema. This operation will try to keep the existing data in the table and put null data in the newly created fields. Note that if a field in removed in the changed schema then the column will be dropped from the table and the data associated with the column or field will be lost. Also for primary key or clustering_order changes, the table must be dropped and data will be lost in the process because cassandra won't allow altering primary key. The module will ask for a confirmation from the user in the terminal whether to perform the required alter/drop operations per changed table.

  • drop will always drop and recreate the table and indexes in case of schema change. This will wipe out all data in that table. It will ask for a confirmation from the user in the terminal whether to perform the required drop operations per changed table.

  • safe will send an error message in callback for any kind of model attribute changes. You need to migrate yourself. This is the recommended setting for production. Note that if NODE_ENV==="production" then regardless of the migration setting, safe is always used to protect inadvertent deletion of your data.

Note that some environments might not support tty console, so asking the user for confirmation in the terminal may throw errors. If you face such problems or want to automate the migration process in a dev/staging environment then you can set the property disableTTYConfirmation: true in the ormOptions. This will do the migrations without asking for a confirmation from the user.

If createKeyspace=false, then it won't be checked whether the specified keyspace exists and, if not, it won't get created automatically.

Now Define a Model named PersonModel.js inside Models Directory


module.exports = {
    fields:{
        name    : "text",
        surname : "text",
        age     : "int"
    },
    key:["name"]
}

Note that a model class name should contain the word Model in it, otherwise it won't be treated as a model class.

Alternatively Load & Organize Models Yourself

Alternatively if you don't want to load your models automatically from a specific directory and want to define and load models yourself, then you can asynchronously load your schemas like the following:

var Cassandra = require('express-cassandra');
var models = Cassandra.createClient({
    clientOptions: {
        contactPoints: ['127.0.0.1'],
        protocolOptions: { port: 9042 },
        keyspace: 'mykeyspace',
        queryOptions: {consistency: Cassandra.consistencies.one}
    },
    ormOptions: {
        defaultReplicationStrategy : {
            class: 'SimpleStrategy',
            replication_factor: 1
        },
        migration: 'safe',
        createKeyspace: true
    }
});

models.connect(function (err) {
    if (err) throw err;

    var MyModel = models.loadSchema('Person', {
        fields:{
            name    : "text",
            surname : "text",
            age     : "int"
        },
        key:["name"]
    }, function(err, UserModel){
        //the table in cassandra is now created
        //the models.instance.Person, UserModel or MyModel can now be used
        console.log(models.instance.Person);
        console.log(models.instance.Person === UserModel);
        console.log(models.instance.Person === MyModel);
    });
});

Important Note on Migrations Support

Current support for migration is an experimental feature and should be set to safe for production environments. When set to alter or drop the ORM will try to take a conservative approach and will ask the user for confirmation when doing any data destructive operation. But as this feature is new and not yet stable, you might encounter some bugs or glitches here and there. Please report an issue in github if you face any. The team will try their best to fix the problem within short time.

Connecting to Cassandra Using Authentication

For connecting to cassandra using authentication, you can use the nodejs-driver authProvider option in the clientOptions object like the following:

clientOptions: {
    contactPoints: ['127.0.0.1'],
    protocolOptions: { port: 9042 },
    keyspace: 'mykeyspace',
    queryOptions: {consistency: models.consistencies.one},
    authProvider: new models.driver.auth.DsePlainTextAuthProvider('my_user', 'my_password')
}

Infact any of the clientOptions supported by the nodejs driver can be used. Possible options are documented in the cassandra driver docs.

Let's Insert Some Data into PersonModel


var john = new models.instance.Person({
    name: "John",
    surname: "Doe",
    age: 32
});
john.save(function(err){
    if(err) {
        console.log(err);
        return;
    }
    console.log('Yuppiie!');
});

Now Let's Find it


models.instance.Person.findOne({name: 'John'}, function(err, john){
    if(err) {
        console.log(err);
        return;
    }
    //Note that returned variable john here is an instance of your model,
    //so you can also do john.delete(), john.save() type operations on the instance.
    console.log('Found ' + john.name + ' to be ' + john.age + ' years old!');
});

Built-in Promise Support

Express-cassandra has built-in promise support powered by bluebird. All the orm functions has an Async suffixed pair function that can be used for promise based async operations instead of using callback. For example, if you want to use promises in the above two insert and find operations, you could do the following:

Insert data using promise (note the Async suffix in function name):


var john = new models.instance.Person({
    name: "John",
    surname: "Doe",
    age: 32
});
john.saveAsync()
    .then(function() {
        console.log('Yuppiie!');
    })
    .catch(function(err) {
        console.log(err);
    });

Find data using promise (note the Async suffix in function name):


models.instance.Person.findOneAsync({name: 'John'})
    .then(function(john) {
        console.log('Found ' + john.name + ' to be ' + john.age + ' years old!');
    })
    .catch(function(err) {
        console.log(err);
    });