Schema Reference
export default {
fields: {
id: {
type: "uuid",
default: {"$db_function": "uuid()"}
},
name: { type: "varchar", default: "no name provided"},
surname: { type: "varchar", default: "no surname provided"},
complete_name: {
type: "varchar",
default: function() {
return this.name + ' ' + this.surname;
}
},
password_hash: "blob",
age: "int",
active: "boolean",
created: {
type: "timestamp",
default: {"$db_function": "toTimestamp(now())"}
}
},
key : [["id"],"created"],
clustering_order: {"created": "desc"},
materialized_views: {
view_name1: {
select: ["name","age"],
key : ["age","created","id"],
},
view_name2: {
select: ["name","age","active"],
key : [["name", "id"],"created"],
clustering_order: {"created": "desc"},
filters: {
created: { $gte: new Date('2017-10-10') },
age: { $isnt: null },
},
}
},
indexes: ["name"],
custom_indexes: [
{
on: 'complete_name',
using: 'org.apache.cassandra.index.sasi.SASIIndex',
options: {}
}
],
table_name: "my_custom_table_name",
methods: {
setPassword: function (password, callback) {
crypto.pbkdf2Sync('secret', 'salt', 100000, 512, 'sha512', function(err, hashed) {
if (err) { return callback(err); }
this.password_hash = hashed;
return callback();
});
}
},
options: {
timestamps: {
createdAt: 'created_at', // defaults to createdAt
updatedAt: 'updated_at' // defaults to updatedAt
},
versions: {
key: '__v' // defaults to __v
}
},
}
What does the above code mean?
-
fields
are the columns of your table. For each column name the value can be a string representing the type or an object containing more specific informations. i.e."id" : { "type": "uuid", "default": {"$db_function": "uuid()"} },
in this example id type isuuid
and the default value is a cassandra function (so it will be executed from the database)."name" : { "type": "varchar", "default": "no name provided"},
in this case name is a varchar and, if no value will be provided, it will have a default value ofno name provided
. The same goes forsurname
.complete_name
the default values is calculated from others field. When the orm processes your model instances, thecomplete_name
will be the result of the function you defined. In the functionthis
is bound to the current model instance. If you need to use the custom datatypes, you may use thethis.get_data_types()
function that will be similar to using models.datatypes but the difference is, it can be used from within a model definition. For example to return a Long value from a default function, you could use thethis.get_data_types().Long
class.age
no default is provided and we could write it just asage: "int"
.active
no default is provided and we could write it just asactive: "boolean"
.created
, like uuid(), will be evaluated from cassandra using thenow()
function.
-
key
: here is where you define the primary key of your table. As you can imagine, the array defines acompound primary key
and the first value of the array is thepartition key
and the others are theclustering keys
. Thepartition key
itself can be an array with multiple fields. When a partition key is an array of multiple fields, it is called acomposite
partition key.The partition key is the key field by which cassandra distributes it's data into multiple machines. So when querying cassandra, in most cases you need to provide the partition key, so cassandra knows which machines or partitions contains the data you are looking for.
The clustering keys are used to keep the data sorted according to the field values of those keys in a partition. So that after getting into a partition, cassandra can find the required data under those partitions very quickly. As the data is sorted according to those keys, cassandra can efficiently seek to find the data it needs.
Understanding the primary key parts is a crucial concept to cassandra data modeling. To get a detailed idea about them, read the cassandra documentation. For your convenience, following are some links to the relevant documentation pages:
Read more about composite keys on the composite key doc
Read more about the compound key here on the compound key documentation
-
clustering_order
: here you can define the clustering order of the clustering keys. If order is not defined, default value of ASC (ascending) is used. -
materialized_views
provides you the ability to define cassandra materialized views for your model table. You may want to read more about it on the materialized view documentation. This is generally suited for querying high cardinality fields. If you need to use select * for the materialized view, you can also useselect: ['*']
. You can also define filters for the data that should be inserted into the materialized view. Only the rows that passes the filter criteria will be available in the materialized view. Note that filters are supported in cassandra 3.10+ only. -
indexes
are the index of your table. It's always an array of field names. You can read more on the index documentation. This is generally suited for querying low cardinality fields, but not as low as boolean fields or fields with very limited number of variants. Very low cardinality fields are not a good separator of large datasets and hence not worthwhile to index. -
custom_indexes
is an array of objects defining the custom indexes for the table. Theon
section should contain the column name on which the index should be built, theusing
section should contain the custom indexer class path and theoptions
section should contain the passed options for the indexer class if any. If nooptions
are required, pass a blank {} object. -
table_name
provides the ability to use a different name for the actual table in cassandra. By default the lowercased modelname is used as the table name. But if you want a different table name instead, then you may want to use this optional field to specify the custom name for your cassandra table. -
methods
allows you to define custom methods for your instances. This can be useful when a single model method should act on various fields and therefore cannot be mapped to a virtual field, or when an asynchronous operation is required for reading or updating a field, such as hashing a password or retrieving related data against a database. -
options
allows you to tell express-cassandra to automatically manage timestamp and version information in your data.
The
timestamps
option if set assigns createdAt and updatedAt fields to your schema and the assigned type is timestamp. Whenever a new document is saved for the schema the createdAt and updatedAt is set automatically to the current timestamp. All save or update operations on the document afterwards will update the updatedAt field automatically. By default, the name of two fields are createdAt and updatedAt, but you can customize the field names by setting timestamps.createdAt and timestamps.updatedAt attributes.The
versions
option if set assigns a version field to your schema and the assigned type is a timeuuid. It automatically saves a unique timeuuid each time the document is saved or updated. By default the name of the field will be __v, but you can customize the field name by setting the versions.key attribute.
When you instantiate a model, every field you defined in schema is automatically a property of your instances. So, you can write:
john.age = 25;
console.log(john.name); //John
console.log(john.complete_name); // undefined.
note: john.complete_name
is undefined in the newly created instance but will be populated when the instance is saved because it has a default value in schema definition
Ok, we are done with John, let's delete him:
john.delete(function(err){
//...
});