Model Class extends sequelize.Model

This is a class that abstracts the tables in the database.
See here for more information on the methods and properties available in your model.

Class Properties

Name Description
protected static table: string The name of the table that the model accesses. This member must be defined in a subclass.
import * as sweet from 'express-sweet';
        
export default class extends sweet.database.Model {
  static get table() {
    return 'user';
  }
}
const Model = require('express-sweet').database.Model;
        
module.exports = class extends Model {
  static get table() {
    return 'user';
  }
}
protected static attributes: sequelize.ModelAttributes List of columns in the table accessed by this model. This member must be defined in a subclass.
import * as sweet from 'express-sweet';

export default class extends sweet.database.Model {
  static get attributes() {
    return {
      id: {
        type: this.DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true
      },
      name: this.DataTypes.STRING,
      email: this.DataTypes.STRING,
      password: this.DataTypes.STRING,
      icon: this.DataTypes.STRING,
      created: this.DataTypes.DATE,
      modified: this.DataTypes.DATE
    };
  }
}
const Model = require('express-sweet').database.Model;

module.exports = class extends Model {
  static get attributes() {
    return {
      id: {
        type: this.DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true
      },
      name: this.DataTypes.STRING,
      email: this.DataTypes.STRING,
      password: this.DataTypes.STRING,
      icon: this.DataTypes.STRING,
      created: this.DataTypes.DATE,
      modified: this.DataTypes.DATE
    };
  }
}
public static readonly DataTypes: {[key: string]: any} A convenience class holding commonly used data types.
This is an alias for sequelize.DataTypes.
See here for details.
{id: this.DataTypes.INTEGER}
public static readonly Op: {[key: string]: any} Operator symbols to be used when querying data. This is an alias for sequelize.Op.
See here for details.
import BookModel from '../models/BookModel';
        
// SELECT * FROM book WHERE title = 'Beautiful' AND genre = 'Nonfiction';
BookModel.findOne({
  where: {
    [BookModel.Op.and]: [
      {title: 'Beautiful'},
      {genre: 'Nonfiction'}
    ]
  }
});

// SELECT * FROM book WHERE title = 'Beautiful' OR title = 'Lose Yourself';
BookModel.findAll({
  where: {
    [BookModel.Op.or]: [
      {title: 'Beautiful'},
      {title: 'Lose Yourself'}
    ]
  }
});

// DELETE FROM user WHERE name = 'Beautiful' OR name = 'Lose Yourself';
BookModel.destroy({
  where: {
    title: {[BookModel.Op.or]: ['Beautiful', 'Lose Yourself']}
  }
});
const BookModel = require('../models/BookModel');
        
// SELECT * FROM book WHERE title = 'Beautiful' AND genre = 'Nonfiction';
BookModel.findOne({
  where: {
    [BookModel.Op.and]: [
      {title: 'Beautiful'},
      {genre: 'Nonfiction'}
    ]
  }
});

// SELECT * FROM book WHERE title = 'Beautiful' OR title = 'Lose Yourself';
BookModel.findAll({
  where: {
    [BookModel.Op.or]: [
      {title: 'Beautiful'},
      {title: 'Lose Yourself'}
    ]
  }
});

// DELETE FROM user WHERE name = 'Beautiful' OR name = 'Lose Yourself';
BookModel.destroy({
  where: {
    title: {[BookModel.Op.or]: ['Beautiful', 'Lose Yourself']}
  }
});
public static readonly fn: (fn: string, ...args: unknown[]) => any Creates an object representing a database function.
This can be used in search queries, both in where and order parts, and as default values in column definitions.
If you want to refer to columns in your function, you should use sequelize.col, so that the columns are properly interpreted as columns and not a strings.
See here for details.
import BookModel from '../models/BookModel';
        
// SELECT upper(`title`) AS `title` FROM `book` AS `book`;
const books = await BookModel.findAll({
  attributes: [[BookModel.fn('upper', BookModel.col('title')), 'title']],
  raw: true
});
// books: [
//   {title: 'MOBY DICK'},
//   {title: 'GET RICH REALLY FAST'},
//    {title: 'FINDING INNER PEACE'}
// ]
const BookModel = require('../models/BookModel');
        
// SELECT upper(`title`) AS `title` FROM `book` AS `book`;
const books = await BookModel.findAll({
  attributes: [[BookModel.fn('upper', BookModel.col('title')), 'title']],
  raw: true
});
// books: [
//   {title: 'MOBY DICK'},
//   {title: 'GET RICH REALLY FAST'},
//   {title: 'FINDING INNER PEACE'}
// ]
public static readonly col: (col: string) => any Creates an object which represents a column in the DB, this allows referencing another column in your query.
This is often useful in conjunction with sequelize.fn, since raw string arguments to fn will be escaped.
See here for details.
public static readonly literal: (val: string) => any Creates an object representing a literal, i.e. something that will not be escaped.
See here for details.
import BookModel from '../models/BookModel';
        
// SELECT
//   `id`,
//   `title`,
//   (SELECT COUNT(*) FROM comment WHERE comment.bookId = book.id) AS `count`
// FROM
//   `book` AS `book`;
const books = await BookModel.findAll({
  attributes: [
    'id',
    'title',
    [BookModel.literal(`(SELECT COUNT(*) FROM comment WHERE comment.bookId = book.id)`), 'count']
  ],
  raw: true
});
// books: [
//   {id: 1, title: 'Beautiful', count: 2},
//   {id: 2, title: 'Lose Yourself', count: 1}
// ]
const BookModel = require('../models/BookModel');
        
// SELECT
//   `id`,
//   `title`,
//   (SELECT COUNT(*) FROM comment WHERE comment.bookId = book.id) AS `count`
// FROM
//   `book` AS `book`;
const books = await BookModel.findAll({
  attributes: [
    'id',
    'title',
    [BookModel.literal(`(SELECT COUNT(*) FROM comment WHERE comment.bookId = book.id)`), 'count']
  ],
  raw: true
});
// books: [
//   {id: 1, title: 'Beautiful', count: 2},
//   {id: 2, title: 'Lose Yourself', count: 1}
// ]
public static readonly where: (attr: sequelize.AttributeType, comparator: string, logic: sequelize.LogicType) => sequelize.Utils.Where A way of specifying attr = condition.
The attr can either be an object taken from Model.rawAttributes (for example Model.rawAttributes.id or Model.rawAttributes.name).
The attribute should be defined in your model definition.
The attribute can also be an object from one of the sequelize utility functions (sequelize.fn, sequelize.col etc.)
For string attributes, use the regular {where: {attr: something}} syntax.
If you don't want your string to be escaped, use sequelize.literal.
See here for details.
import BookModel from '../models/BookModel';
        
// SELECT `title` FROM `book` AS `book` WHERE CHAR_LENGTH(`title`) <= 10;
const books = await BookModel.findAll({
  attributes: ['title'],
  where: BookModel.where(
    BookModel.fn('CHAR_LENGTH', BookModel.col('title')),
    {[BookModel.Op.lte]: 10}
  ),
  raw: true
});
// books: [{title: 'Beautiful'}]
const BookModel = require('../models/BookModel');

// SELECT `title` FROM `book` AS `book` WHERE CHAR_LENGTH(`title`) <= 10;
const books = await BookModel.findAll({
  attributes: ['title'],
  where: BookModel.where(
    BookModel.fn('CHAR_LENGTH', BookModel.col('title')),
    {[BookModel.Op.lte]: 10}
  ),
  raw: true
});
// books: [{title: 'Beautiful'}]
public static readonly QueryTypes: {[key: string]: string} An enum of query types used by sequelize.query.
See here for details.
public static readonly Transaction: (typeof sequelize.Transaction) Reference to sequelize.Transaction.
This includes properties such as isolation level enums used with the transaction option.
See here for details.
const BookModel = require('../models/BookModel');
BookModel.Transaction.ISOLATION_LEVELS.READ_UNCOMMITTED // "READ UNCOMMITTED"
BookModel.Transaction.ISOLATION_LEVELS.READ_COMMITTED // "READ COMMITTED"
BookModel.Transaction.ISOLATION_LEVELS.REPEATABLE_READ  // "REPEATABLE READ"
BookModel.Transaction.ISOLATION_LEVELS.SERIALIZABLE // "SERIALIZABLE"

Class Methods

Name Description
public static association() Associate the model.
Define associations with other models such as hasOne, hasMany, belongsTo, belongsToMany.
This method is called automatically from within the express-sweet.mount method, so you don't have to run it yourself.
See the here for more information.
If you omit the alias (as) option, the associated name will be hasOne, singular for belongsTo, and plural for hasMany.
import * as sweet from 'express-sweet';
import ProfileModel from './ProfileModel';

export default class extends sweet.database.Model {
  static association() {
    // User has one profile.
    this.hasOne(ProfileModel, {
      foreignKey: 'userId', // profile.userId
      sourceKey: 'id', // user.id
      as: 'profile'
    });
  }
}
const Model = require('express-sweet').database.Model;
        
module.exports = class extends Model {
  static association() {
    // User has one profile.
    const ProfileModel = require('./ProfileModel');
    this.hasOne(ProfileModel, {
      foreignKey: 'userId', // profile.userId
      sourceKey: 'id', // user.id
      as: 'profile'
    });
  }
}
public static begin() Starts a transaction and returns a transaction object to identify the running transaction.
This is an alias for the "sequelize.Sequelize.transaction()" method.
See here for details.
Parameters:
  • options?: sequelize.TransactionOptions
    Options provided when the transaction is created.
Return:
  • Promise<sequelize.Transaction> Returns a transaction object to identify the transaction being executed.
import BookModel from '../models/BookModel';
// Simple transaction usage example.
let transaction;
try {
  transaction = await BookModel.begin();
  const book = await BookModel.create({title: 'Beautiful'}, {transaction});
  await transaction.commit();
} catch {
  if (transaction)
    await transaction.rollback();
}

// You can also use transaction options.
let transaction;
try {
  transaction = await BookModel.begin({
    isolationLevel: BookModel.Transaction.ISOLATION_LEVELS.REPEATABLE_READ,
    type: BookModel.Transaction.TYPES.DEFERRED,
  });
  const book = await BookModel.findOne({where: {id: 1}}, {transaction});
  book.title = 'Beautiful';
  await book.save({transaction});
  await transaction.commit();

  // Check the update result.
  // results in: New title of book: Beautiful
  await book.reload();
} catch {
  if (transaction)
    await transaction.rollback();
}
const BookModel = require('../models/BookModel');
        
// Simple transaction usage example.
let transaction;
try {
  transaction = await BookModel.begin();
  const book = await BookModel.create({title: 'Beautiful'}, {transaction});
  await transaction.commit();
} catch {
  if (transaction)
    await transaction.rollback();
}

// You can also use transaction options.
let transaction;
try {
  transaction = await BookModel.begin({
    isolationLevel: BookModel.Transaction.ISOLATION_LEVELS.REPEATABLE_READ,
    type: BookModel.Transaction.TYPES.DEFERRED,
  });
  const book = await BookModel.findOne({where: {id: 1}}, {transaction});
  book.title = 'Beautiful';
  await book.save({transaction});
  await transaction.commit();

  // Check the update result.
  // results in: New title of book: Beautiful
  await book.reload();
} catch {
  if (transaction)
    await transaction.rollback();
}
public static create() Builds a new model instance and calls save on it.
See here for details.
Parameters:
  • values: object
    Hash of data values to create new record with.
  • options: object
    Build and query options.
Return:
  • Promise<Model> Returns a model that contains the data for the added record.
import BookModel from '../models/BookModel';
        
// INSERT INTO `book` (`id`,`title`) VALUES (DEFAULT,'Beautiful');
await BookModel.create({title: 'Beautiful'});
const BookModel = require('../models/BookModel');
        
// INSERT INTO `book` (`id`,`title`) VALUES (DEFAULT,'Beautiful');
await BookModel.create({title: 'Beautiful'});
public static save() Validates this instance, and if the validation passes, persists it to the database.
See here for details.
Parameters:
  • options: object
    save options.
Return:
  • Promise<Model> Returns a model that contains data for manipulated records such as add and update.
import BookModel from '../models/BookModel';
        
// INSERT INTO `book` (`id`,`title`) VALUES (DEFAULT,'Beautiful');
const book = BookModel.build({title: 'Beautiful'});
await book.save();

// UPDATE `book` SET `title`='Lose Yourself' WHERE `id` = 1;
book.title = 'Lose Yourself';
await book.save();
const BookModel = require('../models/BookModel');
        
// INSERT INTO `book` (`id`,`title`) VALUES (DEFAULT,'Beautiful');
const book = BookModel.build({title: 'Beautiful'});
await book.save();

// UPDATE `book` SET `title`='Lose Yourself' WHERE `id` = 1;
book.title = 'Lose Yourself';
await book.save();
public static findOne() Search for a single instance.
Returns the first instance found, or null if none can be found.
See here for details.
Parameters:
  • options: object
    A hash of options to describe the scope of the search.
Return:
  • Promise<Model|null> Returns a Model containing the first data found in the database.
import BookModel from '../models/BookModel';
        
// SELECT `id`, `title`, `created`, `modified` FROM `book` AS `book` LIMIT 1;
await BookModel.findOne();
const BookModel = require('../models/BookModel');
        
// SELECT `id`, `title`, `created`, `modified` FROM `book` AS `book` LIMIT 1;
await BookModel.findOne();
public static findAll() Search for multiple instances.
See here for details.
Parameters:
  • options: object
    A hash of options to describe the scope of the search.
Return:
  • Promise<Array<Model>> Returns a model containing the data found in the database.
import BookModel from '../models/BookModel';
        
// SELECT `id`, `title`, `created`, `modified` FROM `book` AS `book` WHERE `book`.`title` LIKE 'Beautiful%';
await BookModel.findAll({
  where: {
    title: {
      [BookModel.Op.like]: 'Beautiful%'
    }
  }
});
const BookModel = require('../models/BookModel');
        
// SELECT `id`, `title`, `created`, `modified` FROM `book` AS `book` WHERE `book`.`title` LIKE 'Beautiful%';
await BookModel.findAll({
  where: {
    title: {
      [BookModel.Op.like]: 'Beautiful%'
    }
  }
});
public static count() Count the number of records matching the provided where clause.
See here for details.
Parameters:
  • options: object
    A hash of options to describe the scope of the search.
Return:
  • Promise<number> Returns the count of records that match the condition.
import BookModel from '../models/BookModel';
        
// SELECT count(*) AS `count` FROM `book` AS `book`;
await BookModel.count();
const BookModel = require('../models/BookModel');

// SELECT count(*) AS `count` FROM `book` AS `book`;
await BookModel.count();
public static update() Update multiple instances that match the where options.
See here for details.
Parameters:
  • values: object
    hash of values to update.
  • options: object
    update options.
Return:
  • Promise<Array<number, number>> The first element is always the number of affected rows, while the second element is the actual affected rows (only supported in postgres with options.returning true).
import BookModel from '../models/BookModel';
        
// UPDATE `book` SET `title`='Lose Yourself' WHERE `id` = 1;
await BookModel.update({title: 'Lose Yourself'}, {where: {id: 1}});
const BookModel = require('../models/BookModel');

// UPDATE `book` SET `title`='Lose Yourself' WHERE `id` = 1;
await BookModel.update({title: 'Lose Yourself'}, {where: {id: 1}});
public static upsert() Insert or update a single row.
An update will be executed if a row which matches the supplied values on either the primary key or a unique key is found.
Note that the unique index must be defined in your sequelize model and not just in the table.
Otherwise you may experience a unique constraint violation, because sequelize fails to identify the row that should be updated.
See here for details.
Parameters:
  • values: object
    hash of values to upsert.
  • options: object
    upsert options.
Return:
  • Promise<Model, boolean|null> returns record and whether row was created or updated as boolean. For Postgres/SQLite dialects boolean value is always null.
import BookModel from '../models/BookModel';
        
// INSERT INTO `book` (`title`) VALUES (?) ON DUPLICATE KEY UPDATE `title`=VALUES(`title`);
await BookModel.upsert({title: 'Lose Yourself'});
const BookModel = require('../models/BookModel');
        
// INSERT INTO `book` (`title`) VALUES (?) ON DUPLICATE KEY UPDATE `title`=VALUES(`title`);
await BookModel.upsert({title: 'Lose Yourself'});
public static destroy() Delete multiple instances, or set their deletedAt timestamp to the current time if paranoid is enabled.
See here for details.
Parameters:
  • options: object
    destroy options.
Return:
  • Promise<number> The number of destroyed rows.
import BookModel from '../models/BookModel';
        
// DELETE FROM `user` WHERE `id` = 1;
await BookModel.destroy({where: {id :1}});
const BookModel = require('../models/BookModel');
      
// DELETE FROM `user` WHERE `id` = 1;
await BookModel.destroy({where: {id :1}});
public static hasOne() Creates an association between this (the source) and the provided target.
The foreign key is added on the target.
See here for details.
Parameters:
  • target: Model
    The target model.
  • options: object
    hasOne association options.
Return:
For one-to-one association we will use two tables as an example they are User and Profile table.
User table has one Profile table and Profile table belongs to the User table.
Here's the relation diagram for it.
has one relationship
HasOne put the association key in the target model.
Here User can exist without a Profile, but the vice versa is not possible.
This means, we will insert userId field to Profile model’s table.

This is a user model that defines an association in which the user has one profile.
import * as sweet from 'express-sweet';
import ProfileModel from  './ProfileModel';

export default class extends sweet.database.Model {
  static association() {
    // User has one profile.
    this.hasOne(ProfileModel, {
      foreignKey: 'userId', // profile.userId
      sourceKey: 'id', // user.id
      as: 'profile'
    });
  }
}
const Model = require('express-sweet').database.Model;
        
module.exports = class extends Model {
  static association() {
    // User has one profile.
    const ProfileModel = require('./ProfileModel');
    this.hasOne(ProfileModel, {
      foreignKey: 'userId', // profile.userId
      sourceKey: 'id', // user.id
      as: 'profile'
    });
  }
}
This is an example of record search.
import UserModel from '../models/UserModel';
        
// SELECT
//   `user`.`id`,
//   `user`.`name`,
//   `profile`.`id` AS `profile.id`,
//   `profile`.`userId` AS `profile.userId`,
//   `profile`.`address` AS `profile.address`,
//   `profile`.`tel` AS `profile.tel`
// FROM
//   `user` AS `user`
//   LEFT OUTER JOIN `profile` AS `profile` ON `user`.`id` = `profile`.`userId`;
// 
// results in: [
//           {
//             "id": 1,
//             "name": "Robin",
//             "profile": {
//               "userId": 1,
//               "address": "777 Brockton Avenue, Abington MA 2351",
//               "tel": "202-555-0105"
//             }
//           }
//         ]
// 
await UserModel.findAll({
  attributes: ['id', 'name'],
  include: [{
    association: 'profile',
    attributes: ['userId', 'address', 'tel']
  }]
});
const UserModel = require('../models/UserModel');
        
// SELECT
//   `user`.`id`,
//   `user`.`name`,
//   `profile`.`id` AS `profile.id`,
//   `profile`.`userId` AS `profile.userId`,
//   `profile`.`address` AS `profile.address`,
//   `profile`.`tel` AS `profile.tel`
// FROM
//   `user` AS `user`
//   LEFT OUTER JOIN `profile` AS `profile` ON `user`.`id` = `profile`.`userId`;
// 
// results in: [
//           {
//             "id": 1,
//             "name": "Robin",
//             "profile": {
//               "userId": 1,
//               "address": "777 Brockton Avenue, Abington MA 2351",
//               "tel": "202-555-0105"
//             }
//           }
//         ]
// 
await UserModel.findAll({
  attributes: ['id', 'name'],
  include: [{
    association: 'profile',
    attributes: ['userId', 'address', 'tel']
  }]
});
public static belongsTo() Creates an association between this (the source) and the provided target.
The foreign key is added on the source.
See here for details.
Parameters:
  • target: Model
    The target model.
  • options: object
    belongsTo association options.
Return:
For one-to-one association we will use two tables as an example they are User and Profile table.
User table has one Profile table and Profile table belongs to the User table.
Here's the relation diagram for it.
belongs to relationship
BelongsTo put the associations key in the source model.
Here User can exist without a Profile, but the vice versa is not possible.
This means, we will insert userId field to Profile model’s table.

This is a profile model that defines an association whose profile belongs to one user.
import * as sweet from 'express-sweet';
import UserModel from './UserModel';

export default class extends sweet.database.Model {
  static association() {
    // Profile belongs to one user.
    this.belongsTo(UserModel, {
      foreignKey: 'userId',  // profile.userId,
      targetKey: 'id',  // user.id
      as: 'user'
    });
  }
}
const Model = require('express-sweet').database.Model;
        
module.exports = class extends Model {
  static association() {
    // Profile belongs to one user.
    const UserModel = require('./UserModel');
    this.belongsTo(UserModel, {
      foreignKey: 'userId',  // profile.userId,
      targetKey: 'id',  // user.id
      as: 'user'
    });
  }
}
This is an example of record search.
import ProfileModel from  '../models/ProfileModel';
        
// SELECT
//   `profile`.`id`,
//   `profile`.`userId`,
//   `profile`.`address`,
//   `profile`.`tel`,
//   `user`.`id` AS `user.id`,
//   `user`.`name` AS `user.name`
// FROM
//   `profile` AS `profile`
//   INNER JOIN `user` AS `user` ON `profile`.`userId` = `user`.`id`;
// 
// results in: [
//           {
//             "userId": 1,
//             "address": "777 Brockton Avenue, Abington MA 2351",
//             "tel": "202-555-0105",
//             "user": {
//               "id": 1,
//               "name": "Robin"
//             }
//           }
//         ]
await ProfileModel.findAll({
  attributes: ['userId', 'address', 'tel'],
  include: {
    association: 'user',
    required: true,
    attributes: ['id', 'name']
  }
});
const ProfileModel = require('../models/ProfileModel');
        
// SELECT
//   `profile`.`id`,
//   `profile`.`userId`,
//   `profile`.`address`,
//   `profile`.`tel`,
//   `user`.`id` AS `user.id`,
//   `user`.`name` AS `user.name`
// FROM
//   `profile` AS `profile`
//   INNER JOIN `user` AS `user` ON `profile`.`userId` = `user`.`id`;
// 
// results in: [
//           {
//             "userId": 1,
//             "address": "777 Brockton Avenue, Abington MA 2351",
//             "tel": "202-555-0105",
//             "user": {
//               "id": 1,
//               "name": "Robin"
//             }
//           }
//         ]
await ProfileModel.findAll({
  attributes: ['userId', 'address', 'tel'],
  include: {
    association: 'user',
    required: true,
    attributes: ['id', 'name']
  }
});
public static hasMany() Creates a 1:m association between this (the source) and the provided target.
The foreign key is added on the target.
See here for details.
Parameters:
  • target: Model
    The target model.
  • options: object
    hasMany association options.
Return:
For one-to-many association we will use two tables as an example they are User and Comment table.
User table has many Comment table and Comment table belongs to the User table.
Here's the relation diagram for it.
has many relationship
The HasMany put the association key in the target model.
Here user and comments share a one to many relationship.
Each user can make multiple comments while each comment is associated with only a single user.

This is a user model that defines an association in which the user has many comments.
import * as sweet from 'express-sweet';
import CommentModel from './CommentModel';

export default class extends sweet.database.Model {
  static association() {
      // User has many comments.
    this.hasMany(CommentModel, {
      foreignKey: 'userId',  // comment.userId
      sourceKey: 'id',  // user.id
      as: 'comments'
    });
  }
}
const Model = require('express-sweet').database.Model;
        
module.exports = class extends Model {
  static association() {
      // User has many comments.
    const CommentModel = require('./CommentModel');
    this.hasMany(CommentModel, {
      foreignKey: 'userId',  // comment.userId
      sourceKey: 'id',  // user.id
      as: 'comments'
    });
  }
}
This is an example of record search.
import UserModel from  '../models/UserModel';
        
// SELECT
//   `user`.`id`,
//   `user`.`name`,
//   `comments`.`id` AS `comments.id`,
//   `comments`.`userId` AS `comments.userId`,
//   `comments`.`text` AS `comments.text`
// FROM
//   `user` AS `user`
//   LEFT OUTER JOIN `comment` AS `comments` ON `user`.`id` = `comments`.`userId`;
// 
// results in: [
//           {
//             "id": 1,
//             "name": "Robin",
//             "comments": [
//               {
//                 "userId": 1,
//                 "text": "From Robin #1"
//               },
//               {
//                 "userId": 1,
//                 "text": "From Robin #2"
//               }
//             ]
//           }
//         ]
await UserModel.findAll({
  attributes: ['id', 'name'],
  include: {
    association: 'comments',
    attributes: ['userId', 'text']
  }
});
const UserModel = require('../models/UserModel');
        
// SELECT
//   `user`.`id`,
//   `user`.`name`,
//   `comments`.`id` AS `comments.id`,
//   `comments`.`userId` AS `comments.userId`,
//   `comments`.`text` AS `comments.text`
// FROM
//   `user` AS `user`
//   LEFT OUTER JOIN `comment` AS `comments` ON `user`.`id` = `comments`.`userId`;
// 
// results in: [
//           {
//             "id": 1,
//             "name": "Robin",
//             "comments": [
//               {
//                 "userId": 1,
//                 "text": "From Robin #1"
//               },
//               {
//                 "userId": 1,
//                 "text": "From Robin #2"
//               }
//             ]
//           }
//         ]
await UserModel.findAll({
  attributes: ['id', 'name'],
  include: {
    association: 'comments',
    attributes: ['userId', 'text']
  }
});
public static belongsToMany() Create an N:M association with a join table.
Defining through is required.
See here for details.
Parameters:
  • target: Model
    The target model.
  • options: object
    belongsToMany association options.
Return:
For many-to-many association we will use two tables as an example they are User and Book table.
User is marking down Books that he has read. Each user can mark as many books as they want, creating a many to many association between User and Books.
Books can belong to many users.
Here's the relation diagram for it.
belongs to many relationship
The BlongsToMany put the association key in the target model.
Here user and book share a many to many relationship.
Each user can make multiple books, and each book can be associated with multiple users.

This is a user model that defines an association where users and books have a many-to-many relationship.
import * as sweet from 'express-sweet';
import BookModel from './BookModel';

export default class extends sweet.database.Model {
  static association() {
      // Users have many books, and books belong to many users.
    this.hasMany(BookModel, {
      foreignKey: 'userId',  // book.userId
      sourceKey: 'id',  // user.id
      as: 'books'
    });
  }
}
const Model = require('express-sweet').database.Model;
        
module.exports = class extends Model {
  static association() {
      // Users have many books, and books belong to many users.
    const BookModel = require('./BookModel');
    this.hasMany(BookModel, {
      foreignKey: 'userId',  // book.userId
      sourceKey: 'id',  // user.id
      as: 'books'
    });
  }
}
This is an example of record search.
import UserModel from  '../models/UserModel';
        
// SELECT
//   `user`.`id`,
//   `user`.`name`,
//   `books`.`id` AS `books.id`,
//   `books`.`userId` AS `books.userId`,
//   `books`.`title` AS `books.title`
// FROM
//   `user` AS `user`
//   LEFT OUTER JOIN `book` AS `books` ON `user`.`id` = `books`.`userId`;
// 
// results in: [
//           {
//             "id": 1,
//             "name": "Robin",
//             "books": [
//               {
//                 "userId": 1,
//                 "title": "Beautiful"
//               },
//               {
//                 "userId": 1,
//                 "title": "Lose Yourself"
//               }
//             ]
//           }
//         ]
await UserModel.findAll({
  attributes: ['id', 'name'],
  include: {
    association: 'books',
    attributes: ['userId', 'title']
  }
});
const UserModel = require('../models/UserModel');
        
// SELECT
//    `user`.`id`,
//    `user`.`name`,
//    `books`.`id` AS `books.id`,
//    `books`.`userId` AS `books.userId`,
//    `books`.`title` AS `books.title`
//  FROM
//    `user` AS `user`
//    LEFT OUTER JOIN `book` AS `books` ON `user`.`id` = `books`.`userId`;
// 
// results in: [
//           {
//             "id": 1,
//             "name": "Robin",
//             "books": [
//               {
//                 "userId": 1,
//                 "title": "Beautiful"
//               },
//               {
//                 "userId": 1,
//                 "title": "Lose Yourself"
//               }
//             ]
//           }
//         ]
await UserModel.findAll({
  attributes: ['id', 'name'],
  include: {
    association: 'books',
    attributes: ['userId', 'title']
  }
});
public static query() Raw Queries.
As there are often use cases in which it is just easier to execute raw / already prepared SQL queries, you can use the Model.query method.
This is an alias for the "sequelize.Sequelize.query()" method.
See here for details.
Parameters:
  • sql: string
    SQL string.
  • options: object
    Query options.
Return:
  • Promise<any> By default, the function will return two arguments: an array of results, and a metadata object, containing number of affected rows etc. If you are running a type of query where you don't need the metadata, for example a SELECT query, you can pass in a query type to make sequelize format the results.
// By default the function will return two arguments - a results array, and an object containing metadata (such as amount of affected rows, etc).
// Note that since this is a raw query, the metadata are dialect specific.
const [results, metadata] = await BookModel.query("UPDATE book SET title = 'Lose Yourself' WHERE id = 1");

// In cases where you don't need to access the metadata you can pass in a query type to tell sequelize how to format the results. For example, for a simple select query you could do:
// We didn't need to destructure the result here - the results were returned directly
await BookModel.query("SELECT * FROM book", {type: BookModel.QueryTypes.SELECT});