В этом уроке из трех частей мы углубимся в создание приложения для управления списками дел в Node.js и Geddy . Это последняя запись в серии, где мы будем сохранять наши элементы todo
в MongoDB.
Для быстрого обновления в прошлый раз мы создали наш ресурс todo
и создали приложение для работы со списком работ, но данные существовали только в памяти. В этом уроке мы исправим это!
Введение в MongoDB
MongoDB — это база данных хранилища документов NoSQL, созданная людьми в 10gen. Это отличная база данных для приложений Node, потому что она хранит свои данные уже в JSON-подобном формате, а ее запросы написаны на JavaScript. Мы будем использовать его для нашего приложения, поэтому давайте настроим его.
Установка MongoDB
Перейдите по адресу http://www.mongodb.org/downloads и загрузите последнюю версию для вашей ОС. Следуйте инструкциям в readme оттуда. Удостоверьтесь, что вы можете запустить mongod
(и продолжайте и оставьте его mongod
на время этого урока)
Стоит отметить, что вам понадобится запускать Монго в любое время, когда вы хотите, чтобы ваше приложение работало. Большинство людей настраивают это, чтобы запускать со своего сервера, используя сценарий запуска или что-то в этом роде.
Выполнено? Хорошо, давайте двигаться дальше.
MongoDB-обертка
Для нашего приложения мы будем использовать модуль, который обёртывает драйвер базы данных mongodb. Это значительно упрощает код, который мы будем создавать, поэтому давайте его установим. Перейдите в ваше приложение и выполните эту команду:
1
|
npm install mongodb-wrapper
|
Если все идет хорошо, у вас должен быть mongodb-wrapper
в вашем node_modules
.
Настройка вашей базы данных
Mongo — это действительно простая БД для работы; Вам не нужно беспокоиться о настройке таблиц, столбцов или баз данных. Просто подключившись к базе данных, вы создаете ее! И просто добавляя в коллекцию, вы делаете один. Итак, давайте настроим это для нашего приложения.
Редактирование вашего файла init.js
Нам понадобится доступ ко всей нашей config/init.js
, поэтому давайте config/init.js
наш код в config/init.js
Откройте это; это должно выглядеть так:
// Добавить обработчик исключений uncaught-исключений в подобных средах if (geddy.config.environment! = 'development') { process.addListener ('uncaughtException', функция (err) { geddy.log.error (JSON.stringify (ERR)); }); } geddy.todos = []; geddy.model.adapter = {}; geddy.model.adapter.Todo = require (process.cwd () + '/lib/model_adapters/todo').Todo;
Давайте добавим наш код базы данных в самом верху (и удалим массив geddy.todos, пока мы на нем):
var mongo = require ('mongodb-wrapper'); geddy.db = mongo.db («localhost», 27017, «todo»); geddy.db.collection ( 'Todos'); // Добавить обработчик исключений uncaught-исключений в подобных средах if (geddy.config.environment! = 'development') { process.addListener ('uncaughtException', функция (err) { geddy.log.error (JSON.stringify (ERR)); }); } geddy.model.adapter = {}; geddy.model.adapter.Todo = require (process.cwd () + '/lib/model_adapters/todo').Todo;
Во-первых, нам требуется модуль mongodb-wrapper
. Затем мы настраиваем нашу базу данных и добавляем в нее коллекцию. Вряд ли какая-либо настройка вообще.
Переписать вашу модель-адаптер
Гедди на самом деле все равно, какой бэкэнд данных вы используете, если для него написан адаптер модели. Это означает, что единственный код, который вам придется изменить в своем приложении, чтобы todo
свои todo
в базу данных, находится в адаптере модели. Тем не менее, это будет полная перезапись адаптера, поэтому, если вы хотите сохранить старое приложение в памяти, вам нужно скопировать код в другой каталог.
Редактирование вашего метода сохранения
Откройте свой модель-адаптер ( lib/model_adapters/todo.js
) и найдите метод save
. Это должно выглядеть примерно так:
this.save = function (todo, opts, callback) { if (typeof callback! = 'function') { обратный вызов = функция () {}; } var todoErrors = null; for (var i in geddy.todos) { // если он уже есть, сохраните его if (geddy.todos [i] .id == todo.id) { geddy.todos [i] = todo; todoErrors = geddy.model.Todo.create (todo) .errors; обратный вызов (todoErrors, todo); } } todo.saved = true; geddy.todos.push (TODO); обратный вызов (null, todo); }
Сделайте так, чтобы это выглядело так:
this.save = function (todo, opts, callback) { // иногда нам не нужно передавать обратный вызов if (typeof callback! = 'function') { обратный вызов = функция () {}; } // Монго не нравится, когда вы отправляете ему функции // так что давайте удостоверимся, что мы используем только свойства cleanTodo = { id: todo.id , сохранено: todo.saved , название: todo.title , статус: todo.status }; // Двойная проверка, чтобы убедиться, что эта вещь действительна todo = geddy.model.Todo.create (cleanTodo); if (! todo.isValid ()) { возвратный обратный вызов (todo.errors, null); } // Проверяем, есть ли у нас это, чтобы сделать элемент уже geddy.db.todos.findOne ({id: todo.id}, функция (err, doc) { if (err) { обратный вызов (err, null); } // если у нас уже есть элемент to do, обновите его новыми значениями if (doc) { geddy.db.todos.update ({id: todo.id}, cleanTodo, функция (err, docs) { возвратный обратный вызов (todo.errors, todo); }); } // если у нас еще нет элемента, чтобы сделать, сохранить новый еще { todo.saved = true; geddy.db.todos.save (todo, function (err, docs) { обратный вызов (err, docs); }); } }); }
Не слишком пугайтесь этого; Сначала мы начали с самого сложного. Помните, что наш метод save
должен учитывать как новые todo
и обновление старых todo
. Итак, давайте пройдемся по этому коду шаг за шагом.
Мы используем тот же код обратного вызова, что и раньше — если нам не передан обратный вызов, просто используйте пустую функцию.
Затем мы продезинфицируем наш предмет todo
. Мы должны сделать это, потому что наш объект todo
имеет методы JavaScript (например, save
), и Mongo не нравится, когда вы передаете ему объекты с методами. Таким образом, мы просто создаем новый объект только с теми свойствами, которые нам нужны.
Затем мы проверяем, является ли todo
действительной. Если это не так, мы вызываем обратный вызов с ошибками проверки. Если это так, мы продолжим.
В случае, если у нас уже есть этот элемент todo
в БД, мы проверяем его, чтобы увидеть, существует ли todo
. Здесь мы начинаем использовать модуль mongodb-wrapper
. Это дает нам чистый API для работы с нашей базой данных. Здесь мы используем метод db.todos.findOne()
чтобы найти один документ, который соответствует нашему запросу. Наш запрос представляет собой простой объект js — мы ищем документ, id
которого совпадает с id
нашей todo
. Если мы находим его и ошибки нет, мы используем метод db.todos.update()
для обновления документа новыми данными. Если мы не найдем его, мы используем метод db.todos.save()
для сохранения нового документа с данными элемента todo
.
Во всех случаях мы вызываем обратный вызов, когда все готово, с любыми ошибками, которые мы получили, и документами, которые нам возвращала БД, передают на него.
Редактирование всего метода
Взгляните на метод all
, он должен выглядеть так:
this.all = function (callback) { обратный вызов (null, geddy.todos); }
Давайте сделаем так:
this.all = function (callback) { var todos = []; geddy.db.todos.find (). sort ({status: -1, title: 1}). toArray (function (err, docs) { // если есть ошибка, вернемся рано if (err) { обратный вызов (err, null); } // перебираем документы и создаем из них модели for (var i in docs) { todos.push (geddy.model.Todo.create (docs [i])) } обратный вызов (ноль, задачи); }); }
Намного проще, чем метод save
? Мы используем метод db.todos.find()
чтобы получить все элементы коллекции todos
. Мы используем monogdb-wrapper
для sort
результатов по status
(в алфавитном порядке по sort
) и по title
(в алфавитном порядке по возрастанию). Затем мы отправляем это в массив, который запускает запрос для запуска. Как только мы вернем наши данные, мы проверяем, есть ли какие-либо ошибки, если они есть, мы вызываем обратный вызов с ошибкой. Если ошибок нет, мы продолжаем.
Затем мы перебираем все docs
(документы, которые Монго вернул нам), создаем новые экземпляры модели todo
для каждого из них и помещаем их в массив todos
. Когда мы закончим, мы вызываем колбэк, передавая todos
.
Редактирование метода загрузки
Взгляните на метод load, он должен выглядеть примерно так:
this.load = function (id, callback) { for (var i in geddy.todos) { if (geddy.todos [i] .id == id) { возвратный обратный вызов (null, geddy.todos [i]); } } обратный вызов ({сообщение: «Не найдено»}, null); };
Давайте сделаем так:
this.load = function (id, callback) { вар тодо; // найти задачу в БД geddy.db.todos.findOne ({id: id}, function (err, doc) { // если есть ошибка, вернемся рано if (err) { обратный вызов (err, null); } // если есть документ, создайте из него модель if (doc) { todo = geddy.model.Todo.create (doc); } обратный вызов (null, todo); }); };
Этот еще проще. Мы снова используем метод db.todos.findOne()
. На этот раз это все, что мы должны использовать. Если у нас есть ошибка, мы вызываем ее с помощью функции обратного вызова, если нет, мы продолжаем (см. Образец здесь еще?). Если у нас есть документ, мы создаем новый экземпляр модели todo
и вызываем с ним функцию обратного вызова. Вот и все.
Редактирование метода удаления
Посмотрите на метод remove
сейчас, он должен выглядеть так:
this.remove = function (id, callback) { if (typeof callback! = 'function') { обратный вызов = функция () {}; } for (var i in geddy.todos) { if (geddy.todos [i] .id == id) { geddy.todos.splice (i, 1); обратный вызов (ноль); } } обратный вызов ({сообщение: «Не найдено»}); };
Давайте сделаем так:
this.remove = function (id, callback) { if (typeof callback! = 'function') { обратный вызов = функция () {}; } geddy.db.todos.remove ({id: id}, function (err, res) { обратный вызов (ERR); }); }
Метод удаления даже короче, чем раньше. Мы используем метод db.todos.remove()
для удаления любых документов с переданным id
и вызываем обратный вызов с ошибкой (если есть).
Время для магии
Давайте протестируем наше приложение: cd
в каталог вашего проекта и запустите сервер с помощью geddy
. Создать новую todo
. Попробуйте отредактировать его, пропустите некоторые проверки и попробуйте удалить его. Все работает!
Вывод
Надеюсь, вам понравилось изучать Node.js, MongoDB и особенно Geddy. Я уверен, что к настоящему времени у вас есть миллион идей о том, что вы могли бы построить с этим, и я хотел бы услышать о них. Как всегда, если у вас есть какие-либо вопросы, оставьте комментарий здесь или откройте вопрос на github .