Schema definition

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 values
  • BOOL: 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 TagTask gets a tags property (a QueryCollection) containing all its tags and vice versa, Tag gets a tasks property containing all of its tasks.

See also  Recent developments in JavaScript tools: a comprehensive overview

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.

Mix-ins

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’).

See also  Understanding WebAssembly's role in enhancing JavaScript performance

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.