#5 Рефакторим работу с Mongoclient

poster
В этом уроке мы реализуем добавление и удаление исполнителей в базе данных. Порефакторим работу с базой данных, создав отдельный модуль для работы с Mongoclient
Понравилось? Поделитесь с друзьями!
Понравилось?
Поделитесь с друзьями!
Комментарии
Текст видео

В этом видео мы закончим рефакторить наше API добавив методы put и delete. Также мы порефакторим работу с базой данных, вынеся ее в отдельный файл.

Итак давайте добавим сначала put метод.

app.put('/artists/:id', function (req, res) {
  db.collection('artists').updateOne(
    { _id: ObjectID(req.params.id) },
    { name: req.body.name },
    function (err, result) {
      if (err) {
        console.log(err);
        return res.sendStatus(500);
      }
      res.sendStatus(200);
    })
})

Здесь мы вызываем updateOne на коллекцию исполнителей. Первым аргументом идет обьект с полями, по которым мы ищем елемент, который хотим обновить. Вторым аргументом идет обьект данных, которые мы хотим обновить и третьим идет callback, где мы проверяем успешно ли мы обновили запись и если все хорошо, то возвращаем статус 200.

Delete реализовывается по тому же принципу

app.delete('/artists/:id', function (req, res) {
  db.collection('artists').deleteOne(
    { _id: ObjectID(req.params.id) },
    function (err, result) {
      if (err) {
        console.log(err);
        return res.sendStatus(500);
      }
    res.sendStatus(200);
  })
})

Здесь мы применяем deleteOne на коллекцию. Первым аргументом идет обьект с полями по которым мы ищем елемент, а вторым callback, где мы возвращаем success или error.

Мы закончили с вами реализацию API на nodejs, но у нас сервер уже занимает 100 строчек и чем больше мы будем реализовывать, тем сложнее его будет поддерживать. Давайте разобьем его на несколько файлов.

Для начала мы можем вынести работу с базой данных в отдельный файл. Мы хотим, чтобы мы могли работать с базой из любого файла написав

var db = require('./db');

Давайте создадим новый файл db.js и реализуем обетку вокруг метода connect. Мы хотим, чтобы он работал так же как и раньше, но сохранял в локальную переменную db. Также мы хотим, чтобы connect был синглтоном, если коннект к базе у нас уже есть, то мы не открываем еще один коннект а возвращаем существующий.

var MongoClient = require('mongodb').MongoClient;

var state = {
  db: null
};

exports.connect = function (url, done) {
  if (state.db) {
    return done();
  }

  MongoClient.connect(url, function (err, db) {
    if (err) {
      return done(err);
    }
    state.db = db;
    done()
  });
}

Теперь давайте заменим код коннекта в server.js на нашу реализацию.

var db = require('./db');
db.connect('mongodb://localhost:27017/api', function (err, database) {
  if (err) {
    return console.log(err);
  }
  app.listen(3012, function () {
    console.log('API app started');
  })
})

Мы убрали весь код, который записывал базу данных в переменную и саму переменную из server.js. Наш код стал немного чище.

Если мы перезапустим сейчас наш сервер, то connect будет работать правильно, но db.collection будет бросать ошибку, так как такого метода у нас нет. Давайте добавим метод get, который будет возвращать db, с которой мы сможем работать.

exports.get = function () {
  return state.db;
}

Теперь все места, где мы используем db.collection нам нужно заменить на db.get().collection.

db.get().collection('artists')
Только зарегистрированные пользователи могут оставлять комментарии.  Войдите, пожалуйста.
Codename CobWeb
12 месяцев назад
Интересно почему с 3 версией mongodb пишет что db.get() not function, а с твоим кодом и 2й версией все хорошо.
monsterlessons
12 месяцев назад
Потому что создатели всех библиотек (за исключением, может, React) обожают менять API с каждой новой версией. Им кажется, что это клево.
Codename CobWeb
12 месяцев назад
Покапался, вообщем для версии драйвера "mongodb": "^3.0.1", подойдут следующие решения. 1) Тут как решить проблему с db.get() not function (https://stackoverflow.com/questions/47662220/db-collection-is-not-a-function-when-using-mongoclient-v3-0?noredirect=1&lq=1) 2) С put трабла тоже была пока не сделал так ( app.put('/artists/:id', function (req, res) { db.get().collection('artists').updateOne( { _id: ObjectID(req.params.id) }, { $set: {name: req.body.name} }, { upsert: false }, function (err, result) { if (err) { console.log(err); return res.sendStatus(500); } res.sendStatus(200); } ) }) )
monsterlessons
12 месяцев назад
Спасибо, что написали. Думаю это поможет всем, кто устанавливает 3 версию.
Rustam Apaev
1год назад назад
большое спасибо за урок. А чтобы не делать всё это вручную , может порекомендуешь какие-то готовые шаблоны? где всё это уже сделано и осталось пользоваться ) Больше всего меня в бэкенде вопрос авторизации смущает, вроде такая приземленная вещь (которую никто не оценит), но много надо корпеть над ней. (извиняюсь, что вышел за рамки этого видео)
monsterlessons
1год назад назад
На здоровье. Как ORM для ноды из популярных - это mongoose и sequelize, но они достаточно низкоуровневые. Готового фреймворка нет и не предвидится. Для авторизации чаще всего используют passport + дополнительные пакеты (passport-local, passport-oauth). Но опять же оно дает базовые функционал и все обертки нужно писать руками. В ноде все тлен в этом плане)) Из хороших фрейморков для бекенда, где все эти вещи сделаны на нужном уровне и там нужно писать руками намного меньше я бы посоветовал ruby + ruby on rails.
Rustam Apaev
1год назад назад
а так я с метеором знаком... но некоторые вещи пока не смог реализовать в нём. в руби я уже не полезу, наверное