- Documentation
- Quickstart
- Introduction
- Importing thinky
- Schemas
- Relations
- Virtuals
- Feeds
- FAQ
- API
-
- Model
- - getTableName
- - define
- - defineStatic
- - ensureIndex
- - hasOne
- - belongsTo
- - hasMany
- - hasAndBelongsToMany
- - save
- - pre
- - post
- - Query's methods
- - EventEmitter's methods
- - EventEmitter's methods
for documents
- Document
- - getModel
- - merge
- - validate
- - validateAll
- - save
- - saveAll
- - getOldValue
- - isSaved
- - setSaved
- - delete
- - deleteAll
- - purge
- - addRelation
- - removeRelation
- - getFeed
- - closeFeed
- - EventEmitter's methods
- Query
- - getJoin
- - addRelation
- - removeRelation
- - run
- - execute
- - ReQL methods
- - Overwritten ReQL methods
Schemas
Schemas are structures that describe a Model. They are used to validate the
data before saving it.
It can also specify generate some default values if needed.
A schema in thinky is define with an object that is passed to thinky.createModel.
Each field of the object maps to a type. The valid types are:
String
Boolean
Number
Date
Buffer
Object
with{...}
Array
with[...]
"Point"
"virtual"
There are two more ways to define a type, one is via the methods in thinky.type
(referred as thinky.type
). You can create the previous type this way:
type.string()
for aString
. Additional methods that you can chain for this type are:min(number)
: set the minimum length of the stringmax(number)
: set the maximum length of the stringlength(number)
: set the length of the stringalphanum()
: requires the string to be alphanumeric ([a-zA-Z0-9]
)regex(regex[, flags])
: requires the string to match the given regexemail()
: requires the string to be an emaillowercase()
: requires the string to be lowercaseuppercase()
: requires the string to be uppercaseenum(values...)
orenum([enums])
: the possible values for this stringuuid(version)
: requires the string to be a UUID (Supported versions: 3, 4 or 5)
type.boolean()
for aBoolean
type.number()
for aNumber
min(number)
: set the minimum acceptable valuemax(number)
: set the maximum acceptable valueinteger()
: requires the number to be an integer
type.date()
for aDate
min(date)
: set the minimum acceptable value. Note that this will not be enforced for ReQL types liker.now()
max(date)
: set the maximum acceptable value. Note that this will not be enforced for ReQL types liker.now()
type.buffer()
for aBuffer
type.object()
for anObject
type.array()
for anArray
type.point()
for a"Point"
type.virtual()
for a"virtual"
type.any()
for any type. No validation will be performed on this field.
All these types come with a few more methods:
required()
: set the field as required (cannot beundefined
)optional()
: set the field as optional (can beundefined
)allowNull(<boolean>)
: whethernull
is considered valid or not.default(valueOrFunction)
: The first argument can be constant value or a function that will be called with the document as the context.validator(fn)
: a function that will be used to validate a field before saving the document. The function should returntrue
if the field is valid,false
otherwise. The function can also throw an error.
Objects have two extra methods:
allowExtra(<boolean>)
: whether we should allow extra fields and save themremoveExtra()
: remove the fields not defined in the schema before saving
Note: About fields for joined documents:
They should not be declared. The schema of the joined Model will be automatically used.
Note: About dates:
There are three valid values for a Date
:
- A JavaScript Date object, like
new Date()
. - A ReQL raw date object like:
{
$reql_type$: "TIME",
epoch_time: 1397975461.797,
timezone:"+00:00"
}
- An ISO 8601 string like
"2014-04-20T06:32:18.616Z"
.
This format is the one used when you callJSON.stringify
on aDate
(ortoISOString
), which means you can serialize your data between the client and the server without having to worry about parsing the dates.
Note: About points:
You can pass a point as
- an array
[longitude, latitude]
- an object
{longitude: <number>, latitude: <number>}
- a ReQL object
r.point(longitude, latitude)
- a GeoJson point
{type: "Point", coordinates: [longitude, latitude]}
For the moment, thinky
supports only the geometry point. This is mostly because the most common case from far is to store
locations are points, not polygons/lines.
Note: About virtual fields:
Virtual fields are not saved in the database and thinky will therefore not enforce any type on such fields.
Note: About default values:
The default value for a virtual field will be generated once all the other non-virtual values will have been generated. This is the only guarantee. A default value should not rely on another default value.
Example: Create a basic Model for a user
.
var type = thinky.type;
var User = thinky.createModel("User", {
id: type.string(),
name: type.string(),
email: type.string(),
age: type.number(),
birthdate: type.date()
})
Note: About validator:
The reason behind the validator field is that you can import modules that are good at validating data like validator.
Example: Create a model with nested fields.
var type = thinky.type;
var User = thinky.createModel("User", {
id: type.string(),
contact: {
email: type.string(),
phone: type.string()
},
age: type.number()
});
Another way to do it is with:
var type = thinky.type;
var User = thinky.createModel("User", {
id: type.string(),
contact: type.object().schema({
email: type.string(),
phone: type.string()
}),
age: type.number()
});
Example: Create a model where the field scores
is an array of Number
.
var type = thinky.type;
var Game = thinky.createModel("Game", {
id: type.string(),
name: type.string(),
scores: [type.number()]
});
Another way to do it is with:
var type = thinky.type;
var Game = thinky.createModel("Game", {
id: type.string(),
name: type.string(),
scores: type.array().schema(type.number())
});
Example: Create a model where the field game
is an array of objects with two fields — score
and winner
.
var type = thinky.type;
var Game = thinky.createModel("Game", {
id: type.string(),
name: type.string(0,
game: [{
score: type.number(),
winner: type.string()
}]
});
You can also do the same with:
var type = thinky.type;
var Game = thinky.createModel("Game", {
id: type.string(),
name: type.string(),
game: type.array().schema(type.object().schema({
score: Number,
winner: String
}))
});
Example: Create a model for a post where the default value for createdAt
is the
current date if not specified.
var type = thinky.type;
var Post = thinky.createModel("Post",{
id: type.string(),
title: type.string(),
content: type.string(),
createdAt: type.date().default(r.now())
});
Example: Create a model for a user where the nickname, if not defined, will be its first name.
var type = thinky.type;
var Post = thinky.createModel("Post",{
id: type.string(),
firstname: type.string(),
lastname: type.string(),
nickname: type.string().default(function() {
return this.firstname;
}}
});
Example: Create a model for a post
where the field title
must be a String
(where null
will not be a valid value).
var type = thinky.type;
var Post = thinky.createModel("Post",{
id: type.string(),
title: type.string().options({enforce_type: "strict"}),
content: type.string(),
createdAt: type.string().default(r.now())
});
Example: Create a model User
and make sure that the field email is a valid email
using validator
var type = thinky.type;
var validator = require('validator');
var User = thinky.createModel("Users",{
id: type.string(),
email: type.string().validator(validator.isEmail)
age: type.number()
});
Note: With versions prior to 1.15.2, it is possible to declare fields with extra information (options, validator etc.) with a special object:
_type
(mandatory): Can beString
/Boolean
/Number
/Date
/Object
/Array
/Buffer
/'virtual'
.schema
(optional): The schema if the field_type
isObject
orArray
.options
(optional), will overwrite the model’s options:enforce_missing
:Boolean
,true
to forbid missing fields.enforce_extra
: can be"strict"
to forbid fields not defined in the schema,"remove"
to remove fields not declared in the schema, or"none"
enforce_type
: can be"strict"
,"loose"
,"none"
.
default
(optional): can be constant value or a function that will be called with the document as the context.enum
(optional): An array of strings that represent all the possible values for this fields. the document as context.validator
: A function that will be used to validate a field before saving the document. The function should returntrue
if the field is valid,false
otherwise. The function can also throw an error.
This way of declaring types is deprecated since 1.15.2, and is still currently available, but this syntax will eventually be removed.