Статьи

Начало работы с Bookshelf.js

В последние три года мы наблюдаем всплеск популярности JavaScript. За прошедшие годы было предпринято множество попыток перенести популярный язык на сервер . Наиболее распространенной из этих попыток был Node.js , который был представлен сообществу как быстрый способ написания серверных приложений. Точкой продаж для Node была скорость, как с точки зрения производительности, так и времени разработки. С такой популярностью сообщество росло, и проект получил больше участников, что привело к созданию высококачественных модулей, таких как Express.js .

В результате люди начали создавать законченные бэк-энды, используя Node. Одна из самых важных вещей, которую должна выполнять внутренняя система, — это эффективная связь с базами данных. Вот где приходит программное обеспечение Object-Relational Mapping или ORM. Обычно разработчики должны хорошо владеть языком программирования, который они используют, и SQL, чтобы взаимодействовать с базами данных. ORM упрощают жизнь, позволяя разработчикам взаимодействовать с базами данных на выбранном ими языке программирования с помощью объектов. Эта статья знакомит с ORM и рассматривает ORM Bookshelf.js.

Что такое ORM?

Википедия определяет объектно-реляционное отображение как:

техника программирования для преобразования данных между несовместимыми типами
системы в объектно-ориентированных языках программирования. Это создает, в
эффект, «база данных виртуальных объектов», которая может быть использована из
язык программирования

Теперь в нашем случае язык программирования — это JavaScript, а несовместимая система — это система реляционных баз данных, такая как MySQL. Это означает, что библиотека ORM должна позволять нам взаимодействовать с базой данных так же, как мы взаимодействуем с обычными объектами JavaScript. Существует множество библиотек ORM для Node.js, популярными из которых являются Persistence.js , Sequelize.js и Bookshelf.js . Эта статья представит Bookshelf.js.

Bookshelf.js Примеры

Взаимодействие с базой данных обычно сосредоточено вокруг четырех операций CRUD — создание, чтение, обновление и удаление. Bookshelf.js предоставляет интуитивно понятный способ сделать это, например, вот так будет выглядеть операция создания:

new Post({name: 'New Article'}).save().then(function(model) { // ... }); 

Предполагая, что Post является моделью, которая имеет соответствующую таблицу базы данных, а это name является атрибутом, который соответствует столбцу в таблице базы данных.

Аналогично, операция чтения выглядит следующим образом:

 // select * from `user` where `email` = 'user@mail.com' new User({email: 'user@mail.com'}) .fetch() .then(function(model) { console.log(model.get('gender')); }); 

Обратите внимание на вызов в коде. Bookshelf.js поддерживает основанные на обещаниях интерфейсы, что в данном случае означает, что переданная анонимная функция будет вызываться, только если ваш запрос был успешным. model представляет собой результирующий объект JavaScript, который можно использовать для доступа к атрибутам, связанным с User . В нашем случае model.get('gender') возвращает пол нашего пользователя.

Создание API с помощью Bookshelf.js и Express.js

Для более полного примера, предположим, что нам было поручено создать JSON API для блога со следующими ресурсами:

 GET /api/article GET /api/article/:article_id POST /api/article 

И клиент уже имеет базу данных MySQL со следующей таблицей:

 create table article ( id int not null primary key, title varchar(100) null, body text null, author varchar(100) null ); 

Для начала нам нужно настроить нашу среду Express.js с помощью package.json :

 { "name": "article_api", "description": "expose articles via JSON", "version": "0.0.1", "private": true, "dependencies": { "bluebird": "^2.1.3", "body-parser": "^1.3.1", "express": "4.4.3", "mysql": "*", "knex": "*", "bookshelf": "*" } } 

Нам нужен knex запросов knex потому что от него зависит bookshelf , а для обещаний нам нужен bluebird .
Наша структура app.js теперь выглядит так:

 // When the app starts var express = require('express'); var app = express(); var bodyParser = require('body-parser'); var Promise = require('bluebird'); var dbConfig = { client: 'mysql', connection: { host: 'localhost', user: 'root', password: 'your_password', database: 'blog', charset: 'utf8' } }; var knex = require('knex')(dbConfig); var bookshelf = require('bookshelf')(knex); app.set('bookshelf', bookshelf); var allowCrossDomain = function(req, res, next) { res.header('Access-Control-Allow-Origin', '*'); next(); }; app.use(allowCrossDomain); // parse application/x-www-form-urlencoded app.use(bodyParser.urlencoded()); // parse application/json app.use(bodyParser.json()); // parse application/vnd.api+json as json app.use(bodyParser.json({type: 'application/vnd.api+json'})); // elsewhere, to use the bookshelf client: var bookshelf = app.get('bookshelf'); // {our model definition code goes here} app.listen(3000, function() { console.log('Express started at port 3000'); }); 

Наша база данных MySQL называется blog . Нам нужно определить модель товара и привязать ее к таблице article . Мы заменим // {our model definition code goes here} :

 var Article = bookshelf.Model.extend({ tableName: 'article' }); 

Хотите верьте, хотите нет, но это все, что нужно для определения модели в Bookshelf.js. Теперь мы можем использовать эту модель для запроса базы данных в нашем API. Для начала метод GET /api/article должен возвращать все статьи в базе данных:

 app.get('/api/article', function(req, res) { new Article().fetchAll() .then(function(articles) { res.send(articles.toJSON()); }).catch(function(error) { console.log(error); res.send('An error occured'); }); }); 

fetchAll в Bookshelf.js извлекает все записи в таблице базы данных, а catch выполняется только в случае ошибки (в документации есть больше методов модели).

Вывод

Node.js вырос как технология и может использоваться для создания веб-приложений и API через такие модули, как Express.js. Bookshelf.js упрощает взаимодействие с реляционной базой данных с помощью приложения Node.js, оборачивая базовую структуру таблицы базы данных и выставляя обычные объекты JavaScript для запросов. Эта статья обеспечила введение высокого уровня. Полная реализация демонстрационного проекта доступна на GitHub .