Modeling
Basics
We begin defining a data model using a schema.
var userSchema = lounge.schema({
firstName: String,
lastName: String,
age: Number,
usernames: [String],
setup: Boolean
metadata: {
createdAt: Date,
updatedAt: Date
}
})
We can add additional properties using add function:
userSchema.add('name', String)
Alternatively we can explicitly specify the type using type property:
var catSchema = lounge.schema({
name: { type: String }
breed: String,
})
catSchema.add('age', { type: String })
Schema options can be set at construction or using the set function.
var catSchema = lounge.schema({
name: { type: String }
breed: String,
})
catSchema.set('minimize', false)
One a schema is defined we need to generate the model class using the model method.
var Cat = lounge.model('Cat', catSchema)
var myCat = new Cat({
name: 'Felicette',
breed: 'Tabby'
})
console.log(myCat)
We can get an already generated model class using
getModel method.
var Cat = lounge.getModel('Cat')
var cat2 = new Cat({
name: 'Babou',
breed: 'Ocelot'
})
console.log(cat2)
console.log(cat2.modelName) // Cat
Document keys
By default schemas come with an id property as the document key, and the automatically generated value will be
a UUID
using node-uuid v4() function. This should be most practical and
appropriate in a lot of cases. Alternatively you can specify explicit key properties:
var userSchema = lounge.schema({
firstName: String,
lastName: String,
email: { type: String, key: true, generate: false }
})
Here we desire email to be used as the document key and we specify generate: false because we do not want Lounge
to automatically handle key property value generation. If we still want uuid generation but in a different property
we can specify so:
var userSchema = lounge.schema({
firstName: String,
lastName: String,
email: String,
userId: { type: String, key: true, generate: true }
})
generate does not have to be set explicitly to true as that is the default.
We can specify additional prefix and/or suffix for keys. This will be used when writing to the database as the actual document key.
var userSchema = lounge.schema({
firstName: String,
lastName: String,
email: { type: String, key: true, generate: false, prefix: 'user' }
})
Note that setting prefix and suffix options like this will take precedence over any keyPrefix and keySuffix
options specified in the second options parameter to the schema() call or any settings in the lounge config.
Examples
var lounge = require('lounge')
// ... connect
var userSchema = lounge.schema({
name: String
email: { type: String, key: true, generate: false, prefix: 'user::' }
})
var User = lounge.model('User', userSchema)
var user = new User({ name: 'Bob Smith', email: 'bsmith@acme.com' })
user.save()
This will save the user document under key user::bsmith@acme.com.
var lounge = require('lounge')
// ... connect
var userSchema = lounge.schema({
name: String
}, {
keyPrefix: 'user::'
})
var User = lounge.model('User', userSchema)
var user = new User({ name: 'Bob Smith' })
user.save()
This will automatically generate a uuid id property and save the user document under key
similar to user::110ec58a-a0f2-4ac4-8393-c866d813b8d1.
Data manipulation
Data in Model instances can be access directly or using get function. Similarly it can be manipulated using
either assignment operator or using the set function. In either case the input value is validated to be of proper type.
var userSchema = lounge.schema({
name: String
friends: Number,
dob: Date,
setup: Boolean
})
var User = lounge.model('User', userSchema)
var user = new User({ name: 'Bob Smith' })
user.get('name') // 'Bob Smith'
user.name = 'Joe' // OK
user.name.set('Joe') // OK
console.log(user.name) // 'Joe'
user.set('friends', 20) // OK
user.friends = 'abc' // nope. still 20
user.dob = new Date('July 5, 1980')
user.get('dob') // instance of Date
user.set('setup', 'yup') // nope
user.setup = true // OK
Validation
Lounge does automatic validation against input data using the type information specified in the schema definition.
We can provide custom validation in schema definition by providing validator function.
var validator = require('validator') // Node validator module
var userSchema = lounge.schema({
name: String
email: { type: String, validate: validator.isEmail }
})
var User = lounge.model('User', userSchema)
var user = new User({ name: 'Bob Smith' })
user.email = 'bob@gmail.com' // OK
user.email = 'bsmith' // Nope
console.log(user.email) // 'bob@gmail.com'
Virtuals
Virtuals are document properties that you can get and set but that do not get persisted to the database. The getters are useful for formatting or combining fields, while setters are useful for de-composing a single value into multiple values for storage.
var userSchema = lounge.schema({
firstName: String,
lastName: String
})
userSchema.virtual('fullName', {
get: function () {
return this.firstName + ' ' + this.lastName
},
set: function (v) {
if (v !== undefined) {
var parts = v.split(' ')
this.firstName = parts[0]
this.lastName = parts[1]
}
}
})
var User = lounge.model('User', userSchema)
var user = new User({ firstName: 'Bob', lastName: 'Smith' })
console.log(user.fullName) // Bob Smith
user.fullName = 'Jim Jones'
console.log(user.fullName) // Jim Jones
console.log(user.firstName) // Jim
console.log(user.lastName) // Jones
If no set function is defined the virtual is read-only.
Statics
Adding static methods to Models can be accomplished using static() schema function
var userSchema = lounge.schema({
firstName: String,
lastName: String
})
userSchema.static('foo', function(p, q) {
return p + q
})
var User = lounge.model('User', userSchema)
User.foo(1, 2) // 3
We can also pass an object of function keys and function values, and they will all be added.
Methods
Similarly adding instance methods to Models can be done using method() schema function.
var userSchema = lounge.schema({
firstName: String,
lastName: String
})
userSchema.method('fullName', function() {
return this.firstName + ' ' + this.lastName
})
var User = lounge.model('User', userSchema)
var user = new User({firstName: 'Bob', lastName: 'Smith'})
user.fullName() // 'Bob Smith'
We can also pass an object of function keys and function values, and they will all be added.
init() method
There is a special init method that if specified in schema definition will be called at the end of model creation.
You can do additional setup here. This method is not passed in any arguments.
_isNew property
There is a special _isNew property that specified that an instance was created without a key property and that we generated one. This is only applicable for models with schemas where generate is set to true, that is we want Lounge to generate key automatically if not present.
toObject()
Model instances come with toObject function that is automatically used for console.log inspection.
Options:
transform- function used to transform an object once it's been converted to plain javascript representation from a model instance.minimize- to "minimize" the document by removing any empty properties. Default:truevirtuals- to apply virtual gettersserializable- whether to includeserializableproperties. Default:truedateToISO- convert dates to string in ISO format usingDate.toISOString(). Default:true
These settings can be applied on any invocation of toObject as well they can be set at schema level.
var userSchema = lounge.schema({
name: String,
email: String,
password: String
})
var xform = function (doc, ret, options) {
delete ret.password
return ret
}
userSchema.set('toObject', { transform: xform })
var User = lounge.model('User', userSchema)
var user = new User({
name: 'Joe',
email: 'joe@gmail.com',
password: 'password'
})
console.log(user) // { name: 'Joe', email: 'joe@gmail.com' }
toJSON()
Similar to toObject. The return value of this method is used in calls to JSON.stringify.
CAS
All document instances have a read-only property cas that returns the string representation of the CAS object retrieved
from the database. The cas property is initialized only once a document has been retrieved from the database using one
of query functions, or once it has been saved. Alternatively we can use the method getCAS(raw) to get the cas value.
If raw is true then we return the raw CAS object. Otherwise we return string representation. This can be useful
for computation of ETag values for example.
console.log(doc.cas) // String: 00000000a71626e4
console.log(doc.getCAS()) // String: 00000000a71626e4
console.log(doc.getCAS(true)) // Object: CouchbaseCas<11338961768815788032>
Useful member variables
All model instances come with a modelName read only property that you can use to access the model name. As well
instances have schema property that represents the models schema used when creating the model with model() function.
var userSchema = lounge.schema({
name: String,
email: String
})
var User = lounge.model('User', userSchema)
var user = new User({ name: 'Bob Smith' })
console.log(user.modelName) // 'User'
console.log(user.schema instanceof lounge.Schema) // true
Errors
When setting a value fails, an error is generated silently. Errors can be retrieved with getErrors() and cleared with clearErrors().
var schema = new lounge.schema({
id: { type: String, minLength: 5 }
})
var Profile = lounge.model('Profile', schema)
var profile = new Profile()
profile.id = '1234'
console.log(profile.hasErrors()) // true
console.log(profile.getErrors())
// Prints:
[ { errorMessage: 'String length too short to meet minLength requirement.',
setValue: '1234',
originalValue: undefined,
fieldSchema: {
name: 'id',
type: 'string',
minLength: 5
}
} ]
// Clear all errors.
profile.clearErrors()
← Introduction Types →