Если вы разрабатываете веб-приложения, вы почти наверняка будете постоянно взаимодействовать с базой данных. А когда приходит время выбрать способ взаимодействия, выбор может оказаться огромным.

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

Выбор правильной библиотеки базы данных для вашего JavaScript-приложения может иметь большое влияние на ремонтопригодность, масштабируемость и производительность вашего кода, поэтому стоит потратить некоторое время на то, чтобы выяснить ваши варианты.

Наш образец приложения

В качестве примера мы будем использовать простое приложение Express, размещенное на Heroku. Весь код для этой статьи находится в этом репозитории GitHub. Не стесняйтесь клонировать его и следовать.

Предварительные условия

Чтобы запустить пример приложения, вам понадобится следующее программное обеспечение на вашем компьютере:

Если у вас еще нет учетной записи Heroku, вам необходимо зарегистрировать бесплатную учетную запись. Если вы не хотите подписываться на Heroku, вы также можете запустить приложение локально на локальном экземпляре Postgres. Если вас это устраивает, будет довольно легко увидеть, какие изменения вам нужно внести вместо развертывания в Heroku.

После того, как вы установили все вышеперечисленное, запустите heroku login в терминале, и вы готовы приступить к работе.

Сборка и развертывание приложения Hello World

Для начала настроим следующее:

  • Тривиальное приложение Express, которое просто обслуживает веб-страницу Hello, World.
  • База данных Postgres.
  • Две таблицы, представляющие «пользователей» и «комментарии» (у пользователя много комментариев).
  • Некоторые образцы данных (в данном случае сгенерированы через mockaroo.com).

Я создал образец приложения, которое настроит все это за вас (при условии, что вы выполнили heroku login, как указано выше). Чтобы настроить его, выполните следующие команды из командной строки:

git clone https://github.com/digitalronin/query-database-javascript.git

cd query-database-javascript make setup

Это займет несколько минут. Пока вы ждете, вы можете просмотреть make-файл, чтобы увидеть соответствующие команды, которые выполняют следующее:

  • Создайте новое приложение Heroku.
  • Добавьте экземпляр базы данных Postgres.
  • Разверните приложение на Heroku.
  • Запустите команду на Heroku, чтобы настроить таблицы базы данных и импортировать образцы данных CSV.
  • Откройте URL-адрес вашего приложения Heroku в новом окне браузера.

В конце этого процесса вы должны увидеть на веб-странице «Hello, World».

Получение данных с помощью SQL

ОК - все готово! Мы создали базу данных с двумя таблицами и некоторыми примерами данных. Но мы пока ничего не делаем. Следующий шаг - разрешить нашему веб-приложению извлекать данные из базы данных.

Каждый раз, когда вы взаимодействуете с реляционной базой данных, вы делаете это, отправляя команды SQL в сетевой сокет, который база данных прослушивает. Это верно для всех библиотек, которые мы собираемся рассмотреть в этой статье - на самом низком уровне все они отправляют команды SQL в базу данных и получают все возвращаемые выходные данные.

Итак, первый способ, с помощью которого мы рассмотрим взаимодействие с нашей базой данных, - это сделать именно это - отправить команды SQL. Для этого мы собираемся установить библиотеку pg JavaScript, которая позволяет нам отправлять SQL в базу данных Postgres и получать результаты.

Чтобы установить библиотеку pg, выполните следующую команду:

npm install pg

Это приведет к загрузке и установке библиотеки и добавлению ее в файлы package.json и package-lock.json. Давайте зафиксируем эти изменения:

git add package.json package-lock.json git

commit -m "Install the pg library"

Чтобы поговорить с нашей базой данных, нам понадобятся некоторые детали:

  • Имя хоста машины, на которой работает Postgres.
  • Сетевой порт, который прослушивает Postgres.
  • Имя базы данных, в которой находятся наши данные.
  • Имя пользователя и пароль с разрешением на доступ к этим данным.

Большинство библиотек баз данных позволяют нам установить соединение либо путем предоставления объекта в библиотеку, который имеет ключи и значения для всех этих деталей, либо путем объединения их всех в один «URL базы данных», что мы и собираемся сделать. .

Когда вы добавляете базу данных в приложение Heroku, вы автоматически получаете переменную среды с именем DATABASE_URL, содержащую все детали, необходимые для подключения к базе данных. Вы можете увидеть значение вашего DATABASE_URL, запустив:

heroku config

Это выведет все переменные среды, которые может использовать ваше приложение. На данный момент должен быть только один, поэтому в выводе вы должны увидеть что-то вроде этого:

DATABASE_URL: postgres://clqcouauvejtvw:1b079cad50f3ff9b48948f15a7fa52123bc6795b875348d668864
[email protected]:5432/dfb3aad8c026in

В случае нашего примера это выглядит следующим образом:

SQL

{
"hostname": "ec2-52-73-247-67.compute-1.amazonaws.com",

"port": 5432,

"database": "dfb3aad8c026in",
"username": "clqcouauvejtvw",
"password": "1b079cad50f3ff9b48948f15a7fa52123bc6795b875348d66886407a266c0f5b"
}

Ваше значение DATABASE_URL будет другим, но структура останется прежней.

Теперь, когда у нас установлена ​​библиотека pg и мы знаем, как подключиться к нашей базе данных, давайте выполним наш первый пример взаимодействия с базой данных. Мы просто получим список пользователей и отобразим их на нашей веб-странице. В верхней части файла index.js нам понадобится наша библиотека pg и создадим объект подключения к базе данных.

JavaScript

const { Pool } = require('pg');
const conn = new Pool({ connectionString: process.env.DATABASE_URL });

В блоке express() мы изменим строку get для вызова метода, отображающего список пользователей из базы данных:

.get('/', (req, res) => listUsers(req, res))

Наконец, мы реализуем функцию listUsers:

JavaScript

async function listUsers(req, res) {
try {
const db = await conn.connect()
const result = await db.query('SELECT * FROM users');
const results = { users: (result) ? result.rows : null};
res.render('pages/index', results );
db.release();
} catch (err) {
console.error(err);
res.send("Error " + err);
}
}

Этот код ожидает, пока соединение с нашей базой данных не будет установлено, затем отправляет SQL-запрос с помощью функции запроса и получает результат.

Теперь этот шаг может завершиться неудачно по множеству разных причин, поэтому в коде, который мы тестируем, чтобы убедиться, что у нас есть некоторые данные, и, если да, мы назначаем result.rows ключевым пользователям нашего объекта результатов. Затем мы передаем результаты в функцию рендеринга, а затем освобождаем соединение с базой данных.

В views / pages / index.ejs у нас есть доступ к объекту результатов, поэтому мы можем отображать наши пользовательские данные следующим образом:

HTML

<h1>Users</h1>
<ul>
<% users.map((user) => { %>
<li><%= user.id %> - <%= user.first_name %> <%= user.last_name %></li>
<% }); %>
</ul>

Вы можете увидеть код с этими изменениями здесь. first_name и last_name - это имена двух столбцов из таблицы пользователей нашей базы данных.

Давайте развернем эти изменения, чтобы мы могли видеть данные в нашем приложении Heroku:

git add index.js views/pages/index.ejs

git commit -m "Display a list of users"

git push heroku master

Это займет минуту или две. Когда эта команда завершит выполнение, перезагрузите браузер, и вы должны увидеть список пользователей на веб-странице.

Пример MySQL

Приведенный выше пример относится к Postgres, но код для других распространенных реляционных баз данных будет аналогичным. Например, если вы используете MySQL:

  • Вместо npm install pg используйте npm install mysql2 (используйте mysql2, а не mysql - mysql2 быстрее и поддерживает async / await)
  • В index.js вам потребуется mysql следующим образом:

const mysql = require('mysql2/promise');

  • Функция listUsers будет выглядеть так:

JavaScript

async function listUsers(req, res) {
try {
const conn = await mysql.createConnection(process.env.DATABASE_URL);
const [rows, fields] = await conn.execute('SELECT * FROM users');
const results = { 'users': rows };
res.render('pages/index', results );
await conn.end();
} catch (err) {
console.error(err);
res.send("Error " + err);
}
}

views / pages / index.ejs остается прежним.

Вы можете увидеть образец проекта с этими изменениями здесь.

Теперь давайте рассмотрим несколько библиотек, которые строятся на этой основе, добавляя уровни абстракции, которые позволяют вам читать и управлять данными базы данных более «JavaScript-подобным» способом.

До сих пор мы видели, как отправлять необработанный SQL в базу данных; утверждения вроде:

SELECT * FROM users

Если мы хотим получить комментарии от конкретного пользователя, скажем, от пользователя с идентификатором 1, мы могли бы использовать что-то вроде этого:

SELECT * FROM comments WHERE user_id = 1

Нет ничего плохого в таком взаимодействии с вашей базой данных, но это может показаться немного обременительным и требует от вас мысленно «переключать передачи». Вы думаете о своем коде JavaScript одним способом, но когда вам нужно подумать о данных в своей базе данных, вы должны начать думать на SQL.

Задача остальных библиотек баз данных, которые мы собираемся рассмотреть, - позволить вам обрабатывать данные в своей базе данных как объекты и код JavaScript в вашем приложении. «Под капотом» - это все SQL, но вам не нужно особо заботиться об этом, если вы этого не хотите.

Knex - Абстрагирование от SQL

Первая библиотека, о которой мы поговорим, - это Knex. На странице документации Knex описывается как построитель запросов, и его цель - предоставить уровень абстракции поверх необработанного SQL.

Установка Knex

Knex требует pg (или MySQL, если вы используете базу данных MySQL). У нас уже установлен pg, поэтому мы просто добавляем knex следующим образом:

npm install knex

git add package.json package-lock.json

git commit -m "Install the knex library"

Использование Knex

Страница NPM для knex описывает его как «конструктор запросов». Knex в некоторой степени абстрагируется от SQL, но не очень. Нам все еще нужно понимать базовый SQL, но мы можем написать его в синтаксисе, более похожем на JavaScript, вместо того, чтобы разрезать строки SQL. Что еще более важно, мы можем использовать композицию для связывания терминов knex способом, который намного удобнее для программистов JavaScript.

Итак, когда мы использовали pg, у нас было такое выражение:

const result = await db.query('SELECT * FROM users');

Когда мы используем knex, мы можем написать это:

const result = await db.select().from('users');

Это может не показаться большой разницей, но из-за того, как мы можем составлять вызовы функций knex, мы также можем делать такие вещи, как это:

const result = await db.select().from('users').limit(5).offset(8);

Здесь мы получаем 5 пользовательских записей, начиная с позиции 8 в общем наборе всех возможных пользовательских записей, соответствующих нашему запросу. С полным набором опций вы можете ознакомиться в документации knex.

Давайте изменим наше приложение Express, чтобы использовать knex для отображения некоторых записей из нашей базы данных. Сначала в index.js замените эти две строки:

JavaScript

const { Pool } = require('pg');
const conn = new Pool({ connectionString: process.env.DATABASE_URL });

…с этим:

JavaScript

const db = require('knex')({
client: 'pg',
connection: process.env.DATABASE_URL
});

Затем измените реализацию listUsers на это:

JavaScript

async function listUsers(req, res) {
try {
const result = await db.select().from('users').limit(5).offset(5);
const results = { 'users': (result) ? result : null};
res.render('pages/index', results );
} catch (err) {
console.error(err);
res.send("Error " + err);
}
}

Наш файл views / pages / index.ejs может остаться прежним.

Зафиксировать, отправить и развернуть:

git add index.js

git commit -m "Use knex to display user data"

git push heroku master

Когда вы обновите страницу в браузере, вы должны увидеть на странице записи пользователей с 6 по 10.

Вы можете увидеть код с этими изменениями здесь.

Объектно-реляционное отображение (ORM)

Knex дает нам способ взаимодействия с нашей базой данных, который больше похож на JavaScript, но мы все равно должны мыслить ориентированным на базу данных способом, когда нам нужно манипулировать данными.

Следующие три библиотеки, о которых мы собираемся поговорить, построены на основе knex (который построен на основе pg или MySQL) и являются примерами «объектно-реляционного сопоставления» или библиотек ORM. Как следует из названия, целью библиотеки ORM является перевод между данными в реляционной базе данных и объектами JavaScript в вашем приложении. Это означает, что вместо того, чтобы думать о записях в таблице users при написании кода JavaScript, вы можете думать о пользовательских объектах.

Возражение

Первая библиотека, которую мы рассмотрим, - это возражение, она построена на основе knex:

npm install objection

git add package.json package-lock.json

git commit -m "Install the objection library"

Чтобы подчеркнуть некоторые полезности библиотек ORM, мы собираемся изменить наше приложение для отображения пользователей и их комментариев. Возражение построено на основе knex, поэтому в нашем файле index.js мы должны оставить блок knex на месте и добавить немного больше кода (для простоты я помещаю все в файл index.js. В реальном приложении вы бы разбили код на отдельные файлы):

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

Model.knex(db);

Это дает нам класс Model, от которого мы можем унаследовать два класса User и Comment. Сначала мы определим комментарий:

JavaScript

class Comment extends Model {
static get tableName() {
return 'comments';
}
}

Наш класс должен расширять Model и должен реализовывать tableName функцию, чтобы сообщить возражению, какая таблица базы данных содержит базовые записи.

Класс User похож, но мы собираемся добавить некоторое поведение к нашему классу; fullName функция, которую мы можем использовать в нашем шаблоне представления. Мы также собираемся сообщить возражению, что Users имеют Comments (т. Е. У пользователя нет комментариев или больше). На языке ORM это обычно описывается как «имеет много взаимосвязей», т. Е. У пользователя много комментариев. Вот как выглядит код для этого:

JavaScript

class User extends Model {
static get tableName() {
return 'users';
}
fullName() {
return `${this.first_name} ${this.last_name}`;
}
static get relationMappings() {
return {
comments: {
relation: Model.HasManyRelation,
modelClass: Comment,
join: {
from: 'users.id',
to: 'comments.user_id'
}
}
};
}
}

Мы определяем объект relationMappings внутри нашего класса User с одним ключом комментариев и значением, сообщающим возражению, что это HasManyRelation в классе Comment, где значение столбца id таблицы пользователей совпадает со значением столбца user_id в таблица комментариев.

Теперь, когда мы определили наши классы, давайте использовать их в нашем коде. Вот новая реализация listUsers:

JavaScript

async function listUsers(req, res) {
try {
const users = await User.query().limit(5);
for (i in users) {
const user = users[i];
user.comments = await User.relatedQuery('comments').for(user.id);
}
const results = { 'users': users };
res.render('pages/index', results );
} catch (err) {
console.error(err);
res.send("Error " + err);
}
}

Здесь мы выбираем 5 пользователей, затем для каждого из этих пользователей мы извлекаем их комментарии и назначаем их свойству комментариев нашего объекта пользователя. В views / pages / index.ejs мы можем отображать наших пользователей и их комментарии следующим образом:

HTML

<h1>Users</h1>
<ul>
<% users.map((user) => { %>
<li><%= user.id %> - <%= user.fullName() %></li>
<ul>
<% user.comments.map((comment) => { %>
<li><%= comment.body %></li>
<% }); %>
</ul>
<% }); %>
</ul>

Вы можете увидеть код с этими изменениями здесь. Как обычно, зафиксируйте и нажмите для развертывания:

git add index.js views/pages/index.ejs

git commit -m "Show users and comments using Objection"

git push heroku master

Теперь, когда вы перезагрузите страницу, вы должны увидеть пользователей и комментарии.

Проблема «N + 1 выбирает»

Этот код подчеркивает общую проблему, с которой люди сталкиваются при использовании библиотек ORM, известную как проблема «N + 1 выбирает».

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

JavaScript

const users = await User.query().limit(5);
for (i in users) {
const user = users[i];
user.comments = await User.relatedQuery('comments').for(user.id);
}

Это работает, но очень неэффективно. Сначала мы выбираем 5 пользователей, затем для каждого из этих 5 пользователей мы извлекаем их комментарии , делая еще один вызов базы данных. Итак, мы сделали 1 звонок для пользователей, затем еще 5 звонков, чтобы получить комментарии. Это 5 вызовов плюс первая 1, то есть 5 + 1 или N + 1, где N == 5. Следовательно, проблема «N + 1 выбирает».

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

В этом тривиальном примере вы не заметите никакой разницы, но для реальных приложений снижение производительности может быть очень серьезным и вызвать множество проблем.

К счастью, в каждой библиотеке ORM есть функции, которые позволяют легко избежать этой проблемы (при условии, что вы знаете, что она есть). Вот как это работает Objection; в index.js замените блок кода выше следующим:

const users = await User.query().limit(5).withGraphFetched('comments');

Эта одна строка делает то же самое, что и блок кода выше, но гораздо более эффективно для базы данных. Возражение будет использовать предоставленную нами информацию о взаимосвязях, чтобы выяснить, как получить данные пользователя и данные комментариев в одном запросе, а также распаковать и объединить результаты в ту же структуру объектов, которую мы создали перед использованием нашего цикла for.

Вы можете увидеть код с этими изменениями здесь.

Книжная полка

Следующая библиотека ORM, которую мы рассмотрим, - это Книжная полка.

Многие различия между библиотеками ORM зависят от того, для какого варианта использования оптимизирована библиотека. В случае с книжной полкой он явно разработан, чтобы максимально упростить отображение разбитых на страницы списков данных, что является очень распространенным вариантом использования в веб-приложениях.

Давайте заменим возражение на Книжную полку в нашем приложении:

npm uninstall objection

npm install bookshelf

git add package.jsonpackage-lock.json

git commit -m "Replace Objection with Bookshelf"

В index.js замените эти строки:

JavaScript

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

…с этим:

JavaScript

const bookshelf = require('bookshelf')(db);

Замените наши определения классов следующими:

JavaScript

const Comment = bookshelf.model('Comment', {
tableName: 'comments'
});
const User = bookshelf.model('User', {
tableName: 'users',
comments() {
// by default, bookshelf infers that the foreign key is 'user_id'
return this.hasMany('Comment');
}
});

Наша функция listUsers теперь выглядит так:

JavaScript

async function listUsers(req, res) {
try {
const models = await new User()
.fetchPage({
pageSize: 5,
page: 1,
withRelated: ['comments']
});
users = [];
models.map(m => {
const user = m.attributes;
const comments = m.related('comments');
user.comments = comments.map(c => c.attributes);
users.push(user);
});
const results = { 'users': users };
res.render('pages/index', results );
} catch (err) {
console.error(err);
res.send("Error " + err);
}
}

Как видите, определение классов немного более лаконично, но для Книжной полки требуется более подробное определение того, как распаковывать наши данные для построения структуры пользователей / комментариев. Обратите также внимание на то, как концепция страниц данных встроена непосредственно в API библиотеки.

Код в views / pages / index.ejs практически идентичен (я удалил функцию fullName из класса User):

HTML

<h1>Users</h1>
<ul>
<% users.map((user) => { %>
<li><%= user.id %> - <%= user.first_name %> <%= user.last_name %></li>
<ul>
<% user.comments.map((comment) => { %>
<li><%= comment.body %></li>
<% }); %>
</ul>
<% }); %>
</ul>

Посмотреть код с этими изменениями можно здесь. И, конечно же, еще раз выполните фиксацию и развертывание.

git add index.js views/pages/index.ejs

git commit -m "Show users and comments using Bookshelf"

git push heroku master

Продолжить

Последняя библиотека, которую мы собираемся рассмотреть, - это Sequelize.

Sequelize весьма самоуверен в том, как он ожидает структурирования ваших данных. Если вы будете следовать его соглашениям, вы сможете писать меньше кода и позволить Sequelize делать большую часть работы за вас. В частности, у Sequelize есть множество функций, которые помогут создавать таблицы для вас, и по умолчанию он будет создавать их в соответствии со своей собственной структурой и соглашениями об именах.

База данных, которую мы использовали, структурирована не так, как ожидает Sequelize, поэтому нам нужно добавить немного дополнительной конфигурации, чтобы позволить Sequelize работать с ней.

Установка Sequelize

Чтобы удалить книжную полку и установить sequelize, выполните следующие команды:

npm uninstall bookshelf

npm install sequelize

git add package.json package-lock.json

git commit -m "Replace Bookshelf with Sequelize"

Использование Sequelize

В index.js замените эти строки:

JavaScript

const db = require('knex')({
client: 'pg',
connection: process.env.DATABASE_URL
});
const bookshelf = require('bookshelf')(db)

…с этими:

JavaScript

const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize(process.env.DATABASE_URL);

Затем замените определения классов для User и Comment этим кодом:

JavaScript

const User = sequelize.define('User', {
first_name: { type: DataTypes.STRING },
last_name: { type: DataTypes.STRING },
email: { type: DataTypes.STRING }
},
{
tableName: 'users',
timestamps: false
}
);
const Comment = sequelize.define('Comment', {
body: { type: DataTypes.STRING }
}, {
tableName: 'comments',
timestamps: false
}
);
User.hasMany(Comment, { foreignKey: 'user_id' });

Обратите внимание, что мы передали в sequelize.define два объекта. Первый объект определял свойства нашего объекта, а второй содержал некоторые метаданные.

В этом случае мы сказали Sequelize, что таблица базы данных, лежащая в основе класса User, называется 'users' (по умолчанию Sequelize сделает вывод, что таблица называется 'Users'), а timestamps: false сообщает Sequelize, что наша таблица не имеет метки времени. столбцы, называемые createdAt и updatedAt.

Sequelize позволяет очень легко писать код, который будет создавать таблицы для вас, и когда он это делает, он добавляет эти столбцы временных меток и соответственно устанавливает их значения при записи в базу данных. Документация по сиквелизу великолепна, и в ней есть больше об этом.

foreignKey: 'user_id', который мы передаем hasMany, - это еще одно место, где мы должны сообщить Sequelize, что мы не следуем его соглашениям. Он ожидает (и создаст для нас) столбец с именем UserId для ссылки на комментарии пользователей.

Внутри нашей функции listUsers мы можем заменить весь этот код:

JavaScript

const models = await new User()
.fetchPage({
pageSize: 5,
page: 1,
withRelated: ['comments']
});
users = [];
models.map(m => {
const user = m.attributes;
const comments = m.related('comments');
user.comments = comments.map(c => c.attributes);
users.push(user);
});

… С этой единственной строкой:

JavaScript

const users = await User.findAll({ include: Comment });

Мы также должны внести одно крошечное изменение в views / pages / index.ejs. Замените эту строку:

<% user.comments.map((comment) => { %>

… С этим (разница в комментариях пользователя вместо комментариев пользователя):

<% user.Comments.map((comment) => { %>

Вы можете увидеть код с этими изменениями здесь.

git add index.js views/pages/index.ejs

git commit -m "Show users and comments using Sequelize"

git push heroku master

Итак, какой вариант лучше?

Итак, у вас есть 5 способов сделать запрос к реляционной базе данных из вашего приложения JavaScript. Мы начали с необработанного SQL через библиотеку pg / mysql, затем посмотрели на построитель запросов knex, прежде чем перейти к трем библиотекам ORM; возражение, книжная полка и продолжение.

Итак, что лучше всего подходит для вашего приложения?

Как всегда, это зависит от обстоятельств. С библиотекой ORM вы ничего не можете сделать, чего нельзя было бы сделать с помощью построителя запросов или даже необработанного SQL. Поскольку все работает с использованием SQL «под капотом». Это не удивительно. Кроме того, даже если вы решите использовать ORM, большинство библиотек по-прежнему дают вам возможность отправлять необработанный SQL в вашу базу данных. Итак, какой уровень абстракции вы используете, зависит от проблемы, которую вы пытаетесь решить, и от того, на каком коде вы хотите сосредоточить свое внимание.

Если вы интенсивно используете функции своей базы данных, возможно, со сложными представлениями или хранимыми процедурами, вам может быть проще использовать knex или необработанный SQL. Но для большинства веб-приложений вполне вероятно, что библиотека ORM упростит вашу жизнь, абстрагируя структуру таблиц и позволяя рассматривать данные вашего приложения как объекты JavaScript.

Если вы выбрали ORM, выбор какой библиотеки ORM для использования не всегда однозначен. Сфера библиотек JavaScript очень динамична. Новые библиотеки создаются довольно часто, а старые выходят из моды. Вот несколько вещей, о которых следует подумать, делая свой выбор:

  • Просмотрите документацию библиотеки и посмотрите, насколько она ясна и исчерпывающа. Затем решите, имеет ли для вас смысл способ построения API. В разных библиотеках используются разные подходы, и вы можете обнаружить, что одна из них лучше других подходит для ваших требований и предпочтений. Это особенно верно, если вы пишете код для работы с существующей базой данных или создаете базу данных по мере разработки приложения.
  • Взгляните на сообщество вокруг библиотеки. Это то, чем активно пользуются многие люди? Если это так, то, вероятно, вам будет предоставлено множество помощи и советов, если они вам понадобятся. Некоторые библиотеки также имеют обширные экосистемы плагинов, и, возможно, именно эти плагины значительно облегчат вашу жизнь.
  • С этим связана проблема возраста библиотеки. Если он существует какое-то время, более вероятно, что общие проблемы были обнаружены и исправлены. Если это относительно новая библиотека, возможно, вам придется разобраться в большем количестве вещей для себя (что может быть хорошо, если вы любите играть с новыми блестящими игрушками и решать головоломки).
  • Производительность, скорее всего, будет зависеть от того, как вы используете библиотеку, чем от самой библиотеки. Но, если вы абсолютно, безусловно, должны выжать из своего приложения последние несколько микросекунд задержки, тогда работа ближе к базе данных с использованием SQL или knex будет немного быстрее. Имейте в виду, что это обычно весьма незначительное преимущество, и затраты на ремонтопригодность вашего кода, скорее всего, будут выше, чем прирост производительности при тестировании.

Удачного запроса!