# module objection

const objection = require('objection');
const { Model, ref } = require('objection');

The objection module is what you get when you import objection. It has a bunch of properties that are listed below.

# Model

const { Model } = require('objection');

The model class

# initialize

const { initialize } = require('objection');

For some queries objection needs to perform asynchronous operations in preparation, like fetch table metadata from the db. Objection does these preparations on-demand the first time such query is executed. However, some methods like toKnexQuery need these preparations to have been made so that the query can be built synchronously. In these cases you can use initialize to "warm up" the models and do all needed async preparations needed. You only need to call this function once if you choose to use it.

Calling this function is completely optional. If some method requires this to have been called, they will throw a clear error message asking you to do so. These cases are extremely rare, but this function is here for those cases.

You can also call this function if you want to be in control of when these async preparation operations get executed. It can be helpful for example in tests.

# Examples
const { initialize } = require('objection');

await initialize(knex, [Person, Movie, Pet, SomeOtherModelClass]);

If knex has been installed for the Model globally, you can omit the first argument.

const { initialize } = require('objection');

await initialize([Person, Movie, Pet, SomeOtherModelClass]);

# transaction

const { transaction } = require('objection');

The transaction function

# ref

const { ref } = require('objection');

Factory function that returns a ReferenceBuilder instance, that makes it easier to refer to tables, columns, json attributes etc. ReferenceBuilder can also be used to type cast and alias the references.

See FieldExpression for more information about how to refer to json fields.

# Examples
const { ref } = require('objection');

await Model.query()
  .select([
    'id',
    ref('Model.jsonColumn:details.name')
      .castText()
      .as('name'),
    ref('Model.jsonColumn:details.age')
      .castInt()
      .as('age')
  ])
  .join(
    'OtherModel',
    ref('Model.jsonColumn:details.name').castText(),
    '=',
    ref('OtherModel.name')
  )
  .where('age', '>', ref('OtherModel.ageLimit'));

withGraphJoined and joinRelated methods also use : as a separator which can lead to ambiquous queries when combined with json references. For example:

jsonColumn:details.name

Can mean two things:

  1. column name of the relation jsonColumn.details
  2. field name of the details object inside jsonColumn column

When used with withGraphJoined and joinRelated you can use the from method of the ReferenceBuilder to specify the table:

await Person.query()
  .withGraphJoined('children.children')
  .where(ref('jsonColumn:details.name').from('children:children'), 'Jennifer');

# raw

const { raw } = require('objection');

Factory function that returns a RawBuilder instance. RawBuilder is a wrapper for knex raw method that doesn't depend on knex. Instances of RawBuilder are converted to knex raw instances lazily when the query is executed.

Also see the raw query recipe.

# Examples

When using raw SQL segments in queries, it's a good idea to use placeholders instead of adding user input directly to the SQL to avoid injection errors. Placeholders are sent to the database engine which then takes care of interpolating the SQL safely.

You can use ?? as a placeholder for identifiers (column names, aliases etc.) and ? for values.

const { raw } = require('objection');

const result = await Person.query()
  .select(raw('coalesce(sum(??), 0) as ??', ['age', 'ageSum']))
  .where('age', '<', raw('? + ?', [50, 25]));

console.log(result[0].ageSum);

You can use raw in insert and update queries too:

await Person.query().patch({
  age: raw('age + ?', 10)
});

You can also use named placeholders. :someName: for identifiers (column names, aliases etc.) and :someName for values.

await Person.query()
  .select(
    raw('coalesce(sum(:sumColumn:), 0) as :alias:', {
      sumColumn: 'age',
      alias: 'ageSum'
    })
  )
  .where(
    'age',
    '<',
    raw(':value1 + :value2', {
      value1: 50,
      value2: 25
    })
  );

You can nest ref, raw, val and query builders (both knex and objection) in raw calls

const { val } = require('objection')

await Person
  .query()
  .select(raw('coalesce(:sumQuery, 0) as :alias:', {
    sumQuery: Person.query().sum('age'),
    alias: 'ageSum'
  }))
  .where('age', '<', raw(':value1 + :value2', {
    value1: val(50)
    value2: knex.raw('25')
  }));

# val

const { val } = require('objection');

Factory function that returns a ValueBuilder instance. ValueBuilder helps build values of different types.

# Examples
const { val, ref } = require('objection');

// Compare json objects
await Model.query().where(
  ref('Model.jsonColumn:details'),
  '=',
  val({ name: 'Jennifer', age: 29 })
);

// Insert an array.
await Model.query().insert({
  numbers: val([1, 2, 3])
    .asArray()
    .castTo('real[]')
});

# fn

const { fn } = require('objection');

Factory function that returns a FunctionBuilder instance. fn helps calling SQL functions. The signature is:

const functionBuilder = fn(functionName, ...args);

For example:

fn('coalesce', ref('age'), 0);

The fn function also has shortcuts for most common functions:

fn.now();
fn.now(precision);
fn.coalesce(...args);
fn.concat(...args);
fn.sum(...args);
fn.avg(...args);
fn.min(...args);
fn.max(...args);
fn.count(...args);
fn.upper(...args);
fn.lower(...args);

All arguments are interpreted as values by default. Use ref to refer to columns. you can also pass raw instances, other fn instances, QueryBuilders knex builders, knex raw and anything else just like to any other objection method.

# Examples
const { fn, ref } = require('objection');

// Compare nullable numbers
await Model.query().where(fn('coalesce', ref('age'), 0), '>', 30);

// The same example using the fn.coalesce shortcut
await Model.query().where(fn.coalesce(ref('age'), 0), '>', 30);

Note that it can often be cleaner to use raw or whereRaw:

await Model.query().whereRaw('coalesce(age, 0) > ?', 30);

# mixin

const { mixin } = require('objection');

The mixin helper for applying multiple plugins.

# Examples
const { mixin, Model } = require('objection');

class Person extends mixin(Model, [
  SomeMixin,
  SomeOtherMixin,
  EvenMoreMixins,
  LolSoManyMixins,
  ImAMixinWithOptions({ foo: 'bar' })
]) {}

# compose

const { compose } = require('objection');

The compose helper for applying multiple plugins.

# Examples
const { compose, Model } = require('objection');

const mixins = compose(
  SomeMixin,
  SomeOtherMixin,
  EvenMoreMixins,
  LolSoManyMixins,
  ImAMixinWithOptions({ foo: 'bar' })
);

class Person extends mixins(Model) {}

# snakeCaseMappers

const { snakeCaseMappers } = require('objection');

Function for adding snake_case to camelCase conversion to objection models. Better documented here. The snakeCaseMappers function accepts an options object. The available options are:

Option Type Default Description
upperCase boolean false Set to true if your columns are UPPER_SNAKE_CASED.
underscoreBeforeDigits boolean false When true, will place an underscore before digits (foo1Bar2 becomes foo_1_bar_2). When false, foo1Bar2 becomes foo1_bar2.
underscoreBetweenUppercaseLetters boolean false When true, will place underscores between consecutive uppercase letters (fooBAR becomes foo_b_a_r). When false, fooBAR will become foo_bar.
# Examples
const { Model, snakeCaseMappers } = require('objection');

class Person extends Model {
  static get columnNameMappers() {
    return snakeCaseMappers();
  }
}

If your columns are UPPER_SNAKE_CASE

const { Model, snakeCaseMappers } = require('objection');

class Person extends Model {
  static get columnNameMappers() {
    return snakeCaseMappers({ upperCase: true });
  }
}

# knexSnakeCaseMappers

const { knexSnakeCaseMappers } = require('objection');

Function for adding a snake_case to camelCase conversion to knex. Better documented here. The knexSnakeCaseMappers function accepts an options object. The available options are:

Option Type Default Description
upperCase boolean false Set to true if your columns are UPPER_SNAKE_CASED.
underscoreBeforeDigits boolean false When true, will place an underscore before digits (foo1Bar2 becomes foo_1_bar_2). When false, foo1Bar2 becomes foo1_bar2.
underscoreBetweenUppercaseLetters boolean false When true, will place underscores between consecutive uppercase letters (fooBAR becomes foo_b_a_r). When false, fooBAR will become foo_bar.
# Examples
const { knexSnakeCaseMappers } = require('objection');
const Knex = require('knex');

const knex = Knex({
  client: 'postgres',

  connection: {
    host: '127.0.0.1',
    user: 'objection',
    database: 'objection_test'
  }

  ...knexSnakeCaseMappers()
});

If your columns are UPPER_SNAKE_CASE

const { knexSnakeCaseMappers } = require('objection');
const Knex = require('knex');

const knex = Knex({
  client: 'postgres',

  connection: {
    host: '127.0.0.1',
    user: 'objection',
    database: 'objection_test'
  }

  ...knexSnakeCaseMappers({ upperCase: true })
});

For older nodes:

const Knex = require('knex');
const knexSnakeCaseMappers = require('objection').knexSnakeCaseMappers;

const knex = Knex({
  client: 'postgres',

  connection: {
    host: '127.0.0.1',
    user: 'objection',
    database: 'objection_test'
  },

  ...knexSnakeCaseMappers()
});

# knexIdentifierMapping

const { knexIdentifierMapping } = require('objection');

Like knexSnakeCaseMappers, but can be used to make an arbitrary static mapping between column names and property names. In the examples, you would have identifiers MyId, MyProp and MyAnotherProp in the database and you would like to map them into id, prop and anotherProp in the code.

# Examples
const { knexIdentifierMapping } = require('objection');
const Knex = require('knex');

const knex = Knex({
  client: 'postgres',

  connection: {
    host: '127.0.0.1',
    user: 'objection',
    database: 'objection_test'
  }

  ...knexIdentifierMapping({
    MyId: 'id',
    MyProp: 'prop',
    MyAnotherProp: 'anotherProp'
  })
});

Note that you can pretty easily define the conversions in some static property of your model. In this example we have added a property column to jsonSchema and use that to create the mapping object.

const { knexIdentifierMapping } = require('objection');
const Knex = require('knex');
const path = require('path')
const fs = require('fs');

// Path to your model folder.
const MODELS_PATH = path.join(__dirname, 'models');

const knex = Knex({
  client: 'postgres',

  connection: {
    host: '127.0.0.1',
    user: 'objection',
    database: 'objection_test'
  }

  // Go through all models and add conversions using the custom property
  // `column` in json schema.
  ...knexIdentifierMapping(fs.readdirSync(MODELS_PATH)
    .filter(it => it.endsWith('.js'))
    .map(it => require(path.join(MODELS_PATH, it)))
    .reduce((mapping, modelClass) => {
      const properties = modelClass.jsonSchema.properties;
      return Object.keys(properties).reduce((mapping, propName) => {
        mapping[properties[propName].column] = propName;
        return mapping;
      }, mapping);
    }, {});
  )
});

For older nodes:

const Knex = require('knex');
const knexIdentifierMapping = require('objection').knexIdentifierMapping;

const knex = Knex({
  client: 'postgres',

  connection: {
    host: '127.0.0.1',
    user: 'objection',
    database: 'objection_test'
  },

  ...knexIdentifierMapping({
    MyId: 'id',
    MyProp: 'prop',
    MyAnotherProp: 'anotherProp'
  })
});

# ValidationError

const { ValidationError } = require('objection');

The ValidationError class.

# NotFoundError

const { NotFoundError } = require('objection');

The NotFoundError class.

# DBError

const { DBError } = require('objection');

The DBError (opens new window) from db-errors (opens new window) library.

# ConstraintViolationError

const { ConstraintViolationError } = require('objection');

The ConstraintViolationError (opens new window) from db-errors (opens new window) library.

# UniqueViolationError

const { UniqueViolationError } = require('objection');

The UniqueViolationError (opens new window) from db-errors (opens new window) library.

# NotNullViolationError

const { NotNullViolationError } = require('objection');

The NotNullViolationError (opens new window) from db-errors (opens new window) library.

# ForeignKeyViolationError

const { ForeignKeyViolationError } = require('objection');

The ForeignKeyViolationError (opens new window) from db-errors (opens new window) library.

# CheckViolationError

const { CheckViolationError } = require('objection');

The CheckViolationError (opens new window) from db-errors (opens new window) library.

# DataError

const { DataError } = require('objection');

The DataError (opens new window) from db-errors (opens new window) library.