Часть 2 - Objection.js

Objection.js - это еще одна ORM для Node.js (как и Sequelize), цель которой - максимально упростить для вас использование всей мощи SQL, а также базового механизма базы данных, при этом делая обычные вещи простыми и приятными. .

- Согласно Официальной документации Objection.js

Чтобы лучше понять, как работает ObjectionJS, мы воспользуемся концепцией системы онлайн-покупок. Для простоты мы будем просто играть со следующими двумя объектами: i) Customer, ii) Order. Где каждый клиент может разместить один или несколько заказов, и каждый заказ принадлежит одному клиенту.

1) Установка

Вы можете использовать npm или yarn для установки Objection.js. Objection использует knex SQL Query Builder в фоновом режиме в качестве уровня доступа к базе данных, поэтому вам также необходимо установить его.

npm install objection knex

yarn add objection knex

Вам также придется вручную установить один из следующих драйверов для выбранной вами базы данных:

npm install pg
npm install sqlite3
npm install mysql
npm install mysql2

Все примеры, представленные в этой статье, будут основаны на драйвере MySQL, то есть mysql2. Кроме того, база данных работает на моем локальном компьютере.

2) Установите соединение с базой данных

Поместите следующий код в свой ./util/database.js

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

// Initialize knex.
const knex = Knex({
  client: 'mysql',
  connection: {
    host: "127.0.0.1",
    user: "your_username", //replace with your username
    password: "your_password", //replace with your password
    database: "your_db_name" // replace with your db name
  },
});

// Give the Knex instance to Objection.
Model.knex(knex);

module.exports = knex;

3) Определите модели и определите взаимосвязь

Модель - это абстракция, представляющая таблицу в вашей базе данных. В возражении это класс, расширяющий класс Модель.

Определите модель клиента, поместив следующий код в свой ./models/customer.js

const { Model } = require('objection');
const Order = require('./order');

class Customer extends Model {
  static get tableName() {
    return 'customers';
  };

  $beforeInsert() {
    this.createdAt = new Date();
  };

  $beforeUpdate() {
    this.updatedAt = new Date();
  };

  static get nameColumn() {
    return 'name';
  };

  static get emailColumn() {
    return 'email';
  };

  static get jsonSchema() { //Optional JSON Schema Validation
    return {
      type: 'object',
      required: ['name', 'email'],
      properties: {
        id: { type: 'integer' },
        name: { type: 'string', minLength: 1, maxLength: 255 },
        email: { type: 'string' },
        createdAt: { type: 'string' },
        updatedAt: { type: 'string' }
      }
    };
  };

  static relationMappings = {
    order: {
      relation: Model.HasOneRelation,
      modelClass: Order,
      join: {
        from: 'customers.id',
        to: 'orders.customer_id'
      }
    }
  };

};

module.exports = Customer;

У каждого клиента есть идентификатор, имя и адрес электронной почты. Это представляет 3 поля / столбца таблицы Customer. Итак, модель Order связана с моделью Customer отношением hasOne. Теперь мы должны сообщить Objection об этой ассоциации, и мы сделаем это, определив relationMappings object.

Определите модель заказа, поместив следующий код в свой ./models/order.js

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

class Order extends Model {
  static get tableName() {
    return 'orders';
  };

  $beforeInsert() {
    this.createdAt = new Date();
  };

  $beforeUpdate() {
    this.updatedAt = new Date();
  };

  static get totalColumn() {
    return 'total';
  };

  static get customerIdColumn() {
    return 'customer_id';
  };

  static get jsonSchema() { //Optional JSON Schema Validation
    return {
      type: 'object',
      required: ['total'],
      properties: {
        id: { type: 'integer' },
        total: { type: 'number' },
        customer_id: { type: 'integer' },
        createdAt: { type: 'string' },
        updatedAt: { type: 'string' }
      }
    };
  };
};

module.exports = Order;

У каждого заказа будет идентификатор и общая цена покупки. Это представляет 2 поля / столбца таблицы заказов.

4) Написание запросов

В следующем фрагменте кода мы выполняем следующие действия:

i) Удалите всех ранее существовавших клиентов / заказов из базы данных.

ii) Вставьте нового клиента.

iii) Получите список всех клиентов в нашей таблице Customer.

iv) Вставьте новый заказ для этого клиента, используя внешний ключ customerId.

v) Выбрать все заказы для текущего клиента.

const Customer = require('./models/customer');
const Order = require('./models/order');
const knex = require('./util/database');

async function main() {
    await Customer.query().delete();
    await Order.query().delete();
  
    // Insert one row to the database.
    const customer = await Customer.query().insert({
      name: 'Rachel Green',
      email: '[email protected]',
    });
  
    // Read all rows from the db.
    const customerRead = await Customer.query();
    console.log(customerRead);

    const order = await Customer.relatedQuery('order')
                        .for(customer.id)
                        .insert({ total: 55 });
    console.log(order);

    const orderTotal = await Order.query()
                                .select('total')
                                .where('customer_id', '=', customer.id)
                                .orderBy('total');
    
    console.log(orderTotal);
  }
  
  main()
    .then(() => knex.destroy())
    .catch((err) => {
      console.error(err);
      return knex.destroy();
    });

Кроме того, не забудьте уничтожить объект knex, когда закончите!

Итак, вот и все об этой полезной ORM для Node.js. Я надеюсь, что информация, представленная в этой статье, будет вам полезна и поможет вам упростить и оптимизировать манипуляции с базой данных. Кроме того, вы можете прочитать первую часть этой серии, посвященную ORM, прямо здесь: Можете ли вы общаться с базами данных, не изучая SQL, часть 1 - Продолжение.

Дополнительные ресурсы:

Первоначально опубликовано на https://www.theimmigrantprogrammers.com.