A data model is declared using persistence.define. The following two
definitions define a Task and Category entity with a few simple
properties. The property types are based on SQLite
types, specifically supported
types are (but any SQLite type is supported):
TEXT: for textual data INT: for numeric valuesBOOL: for boolean values (true or false)DATE: for date/time value (with precision of 1 second)JSON: a special type that can be used to store arbitrary
JSON data. Note that this data can not be used
to filter or sort in any sensible way. If internal changes are made to a JSON
property, persistence.js may not register them. Therefore, a manual
call to anObj.markDirty('jsonPropertyName') is required before calling
persistence.flush.Example use:
var Task = persistence.define('Task', {
name: "TEXT",
description: "TEXT",
done: "BOOL"
});
var Category = persistence.define('Category', {
name: "TEXT",
metaData: "JSON"
});
var Tag = persistence.define('Tag', {
name: "TEXT"
});
The returned values are constructor functions and can be used to create new instances of these entities later.
It is possible to create indexes on one or more columns using
EntityName.index, for instance:
Task.index('done');
Task.index(['done', 'name']);
These indexes can also be used to impose unique constraints :
Task.index(['done', 'name'],{unique:true});
Relationships between entities are defined using the constructor
function's hasMany call:
// This defines a one-to-many relationship:
Category.hasMany('tasks', Task, 'category');
// These two definitions define a many-to-many relationship
Task.hasMany('tags', Tag, 'tasks');
Tag.hasMany('tasks', Task, 'tags');
The first statement defines a tasks relationship on category objects
containing a QueryCollection (see the section on query collections
later) of Tasks, it also defines an inverse relationship on Task
objects with the name category. The last two statements define a
many-to-many relationships between Task and Tag. Task gets a
tags property (a QueryCollection) containing all its tags and vice
versa, Tag gets a tasks property containing all of its tasks.
The defined entity definitions are synchronized (activated) with the
database using a schemaSync call, which takes a callback
function (with a newly created transaction as an argument), that is called
when the schema synchronization has completed, the callback is
optional. Depending on your environment you call schemaSync either on the persistence (client-size use) or on your session object (in server environments):
persistence.schemaSync();
// or, with a callback:
persistence.schemaSync(function(tx) {
// tx is the transaction object of the transaction that was
// automatically started
});
And using session (in server environments):
session.schemaSync();
// or, with a callback:
session.schemaSync(function(tx) {
// tx is the transaction object of the transaction that was
// automatically started
});
There is also a migrations plugin you can check out, documentation can be found in persistence.migrations.docs.md.
You can also define mix-ins and apply them to entities of the model.
A mix-in definition is similar to an entity definition, except using
defineMixin rather than just define. For example:
var Annotatable = persistence.defineMixin('Annotatable', {
lastAnnotated: "DATE"
});
You can define relationships between mix-in and entities. For example:
// A normal entity
var Note = persistence.define('Note', {
text: "TEXT"
});
// relationship between a mix-in and a normal entity
Annotatable.hasMany('notes', Note, 'annotated');
Once you have defined a mix-in, you can apply it to any entity of your model,
with the Entity.is(mixin) method. For example:
Project.is(Annotatable);
Task.is(Annotatable);
Now, your Project and Task entities have an additional lastAnnotated property.
They also have a one to many relationship called notes to the Note entity.
And you can also traverse the reverse relationship from a Note to its annotated object.
Note that annotated is a polymorphic relationship as it may yield either a Project
or a Task (or any other entity which is `Annotatable').
Note: Prefetch is not allowed (yet) on a relationship that targets a mixin. In the example above
you cannot prefetch the annotated relationship when querying the Note entity.
Notes: this feature is very experimental at this stage. It needs more testing. Support for "is a" relationships (classical inheritance) is also in the works.