MongoDB Подробное руководство
MongoDB состоит из: БД, которые состоят из коллекций. Коллекции, в свою очередь, состоят из документов. Каждый документ состоит из полей. www.mongodb.com
MongoDB клиенты
Конфиг
В папке bin
создайте файл и назовите его mongodb.config
.
Указываем в этом файле путь, где будем хранить БД, например, для windows: dbpath=c:\mongodb\data
Запуск
mongod
— это серверmongo
— клиентская консоль
Стартуем mongod (сервер):
mongod --config c:\mongodb\bin\mongodb.config
// не забудьте заранее создать папку data
Команда mongo
позволяет подключиться к запущенному серверу (стартуем mongo
оболочку/shell).
mongo
Работа с БД
Выводим все БД в mongo:
show dbs
Переходим (и одновременно создаем) к нужной БД
use name_bd
Команды db
возвращает имя БД, внутри которой мы сейчас находимся:
db
//test
Коллекции
Показать все коллекции в БД
show collections
Метод find()
Показать весь контент нужной коллекции
db.collection_name.find()
Пример:
db.band.find()
db.band.find().pretty()
Метод pretty
выводит результат в удобном для чтения виде.
Метод count()
Метод count
выводит количество документов в коллекции:
db.band.count()
Метод remove()
Метод remove
используется, чтобы удалить документ из коллекции (или всю коллекцию).
db.unicorns.remove({name: "Leto"})
Метод insert()
Заносим данные в коллекцию band
(и, видимо, создаем тем самым коллекцию band
, если ее нет):
db.band.insert({name: 'Queen', bid: '3'})
Добавим составы в коллекцию band
:
db.band.update({bid: '1'}, {$set: {members: [{name: "Jimmy Page", id: "1"}, {name: "robert Plant", id: "2"}, {name: "John Bonham", id: "3"}, {name: "John Paul Jones", id: "4"}]}})
db.band.update({bid: '2'}, {$set: {members: [{name: "Syd Barret", id: "5"}, {name: "Roger Waters", id: "6"}, {name: "Nick Mason", id: "7"}, {name: "Richard Wright", id: "8"}, {name: "David Gilmour", id: "9"}]}})
Мы можем добавлять данные, не декларируя их предварительно: свойство members
. Отсутствует схема: легко добавили массив объектов.
Модификация данных
Оператор $set
Оператор $set
заставляет команду update
модифицировать лишь те ключи, которые ему переданы (см. пример выше).
Оператор $unset
Оператор $unset
удаляет указанный ключ
db.collection.update({id: 2}, {$unset: {myKey: 1}});
db.example.update({}, {$unset: {words:1}}, false, true);
Оператор $inc
Оператор $inc
увеличивает значение поля на указанную величину
db.collection.update({id: 2}, {$inc: {myCounter: 111}});
db.collection.update( {"players.playerName":"Joe"}, { $inc : { "players.$.playerScore" : 1 } }
Оператор $rename
Оператор $rename
позволяет переименовать поля
db.collection.update({id: 2}, {$rename: {"old_name": "new_name"}});
db.band.update({bid: "1"},{$rename:{"members":"members_new"}});
Индексы
metanit.com/nosql/mongodb proselyte.net/tutorials/mongodb/indexing
Индексация поддерживает эффективное выполнение запросов. Без индексов MongoDB необходимо сканировать каждый документ коллекции для выбора тех документов, которые соответствуют запросу. Данный процесс крайне не эффективен и требует обработки большого количества данных.
Индексы – это специальные структуры данных, которые хранят небольшие части данных в форме, которая легко распознаётся. Они хранят значение определённого поля или набора полей, упорядоченных по значению поля, указанному в индексе.
Построим индекс по ключу bid
:
db.band.ensureIndex({bid: 1})
ensureIndex
устарел, начиная с версии 3.0, в данный момент является псевдонимом для db.collection.createIndex()
.
Схемы и модели
Схемы определяют структуру документов внутри коллекции, а модели используются для создания копий данных, хранящихся в документах.
I Основы
- 1. Внутри MongoDB может быть ноль или более баз данных.
- 2. База данных может иметь ноль или более «коллекций». (коллекция практически тоже что и таблица)
- 3. Коллекции состоят из нуля или более «документов». Опять же, документ можно рассматривать как «строку».
- 4. Документ состоит из одного или более «полей», которые — как можно догадаться — подобны «колонкам».
- 5. «Индексы» в MongoDB почти идентичны таковым в реляционных базах данных.
- 6. Важно понимать, что когда мы запрашиваем у MongoDB какие-либо данные, то она возвращает курсор, с которыми мы можем делать все что угодно.
Но есть отличия:
Основное различие в том, что реляционные базы данных определяют «колонки» на уровне «таблицы», в то время как документ-ориентированные базы данных определяют «поля» (в реляционных «колонки») на уровне «документа» (в релационных «запись»).
В конечном счёте дело в том, что коллекция не содержит информации о структуре содержащихся в ней данных. Информацию о полях содержит каждый отдельный документ.
Метод insert
Мы не обязаны создавать коллекции явно. Мы просто можем вставить документ в новую коллекцию. Чтобы это сделать, используйте команду insert
, передав ей вставляемый документ:
db.unicorns.insert({name: 'Aurora', gender: 'f', weight: 450})
Селекторы запросов
Селектор запросов MongoDB (это JSON-объект) аналогичен предложению where
SQL-запроса. Как таковой он используется для поиска, подсчёта, обновления и удаления документов из коллекций.
Селектор — это JSON-объект, в простейшем случае это может быть даже {}
, что означает выборку всех документов (аналогичным образом работает null
). Если нам нужно выбрать всех единорогов (англ. «unicorns») женского рода, можно воспользоваться селектором {gender:'f'}
.
{поле: значение}
используется для поиска всех документов, у которых есть ‘поле’ и у него есть ‘значение’.
{поле1: значение1, поле2: значение2}
работает как логическое И
.
Оператор $lt, $lte, $gt, $gte, $ne
Специальные операторы $lt
, $lte
, $gt
, $gte
и $ne
используются для выражения операций «меньше», «меньше или равно», «больше», «больше или равно», и «не равно».
Пример использовани селекторов с командой find
(но также селекторы могут быть использованы с remove
, count
, update
):
Например, чтобы получить всех самцов единорога, весящих более 700 фунтов, мы можем написать:
db.unicorns.find({gender: 'm', weight: {$gt: 700}})
Оператор $exists
Оператор $exists
используется для проверки наличия или отсутствия поля, например:
db.unicorns.find({vampires: {$exists: false}})
Оператор $or
Оператор $or
используется как ИЛИ
db.unicorns.find({gender: 'f', $or: [{loves: 'apple'}, {loves: 'orange'}, {weight: {$lt: 500}}]})
//... или любят яблоки, или любят апельсины, или весят менее 500 фунтов
Отметьте
db.unicorns.insert({name: 'Leia', dob: new Date(2001, 9, 8, 14, 53), loves: ['apple', 'watermelon'], weight: 601, gender: 'f', vampires: 33});
Поле loves
это массив. MongoDB поддерживает массивы как объекты первого класса. Самое интересное это та простота, с которой делается выборка по значению массива: {loves: ‘watermelon’} вернёт нам все документы, у которых watermelon
является одним из значений поля loves
.
Оператор $where
Оператор $where
(в след. разделах)
Самый гибкий оператор — $where
, позволяющий нам передавать JavaScript для его выполнения на сервере.
Оператор ObjectId
ObjectId, сгенерированный MongoDB для поля _id, подставляется в селектор следующим образом:
db.unicorns.find({_id: ObjectId("TheObjectId")})
II update
В простейшей форме, update
принимает 2 аргумента: селектор для выборки и то, чем обновить соответствующее поле. Второй параметр используется для полной замены оригинала:
db.unicorns.update({name: 'Roooooodles'}, {weight: 590})
По умолчанию, update обновляет лишь первый найденный документ
Модификатор $set
Модификатор $set
обновляет конкретные поля, а не весь документ.
Если вам нужно всего лишь изменить пару полей, лучше всего использовать модификатор $set
:
db.unicorns.update({weight: 590}, {$set: {name: 'Roooooodles', dob: new Date(1979, 7, 18, 18, 44), loves: ['apple'], gender: 'm', vampires: 99}})
db.unicorns.update({name: 'Roooooodles'}, {$set: {weight: 590}})
Другие модификаторы, которые действуют непосредственно на поля, а не на весь документ:
модификатор $inc
модификатор $inc
— увеличить или уменьшить значение поля.
db.unicorns.update({name: 'Pilot'}, {$inc: {vampires: -2}})
модификатор $push
— позволяет добавить данные в массив
db.unicorns.update({name: 'Aurora'}, {$push: {loves: 'sugar'}})
Обновление/вставка (при отсутствии элемента)
Не забывайте использовать модификатор $set
, если вам нужно обновить лишь некоторые поля.
Разрешаем вставку при обновлении (3-й параметр)
Чтобы разрешить вставку при обновлении (если элемент не будет найден), установите третий параметр в true
.
db.hits.update({page: 'unicorns'}, {$inc: {hits: 1}});
db.hits.find();
Вставки и обновления не будет, так как 3-й параметр опущен, а документа с {page: 'unicorns'}
отсутствует в коллекции.
db.hits.update({page: 'unicorns'}, {$inc: {hits: 1}}, true);
db.hits.find();
Поскольку документы с полем page
, равным unicorns
, не существуют, то будет создан новый документ. Если выполнить это вторично, существующий документ будет обновлён, и поле hits
увеличится до 2.
Одновременно создастся коллекция hits
, если она отсутствует.
Множественные обновления (4-й параметр)
Чтобы обновить множество документов нужно установить четвертый параметр в true
:
db.unicorns.update({}, {$set: {vaccinated: true }}, false, true);
Этим мы обновили все поля добавив везде поле vaccinated
со значением true
III Команда find (курсор)
Курсор базы данных — это объект БД, который позволяет приложениям работать с записями «по-одной», а не с множеством сразу. То есть курсор (как мы помним это объект), который позволяет передвигаться по выборке (назад на одно, вперед на одну, в конец/начало) при помощи своих методов.
Как уже упоминалось, результатом find
является курсор. Второй необязательный параметр у find
это список полей, которые мы хотим получить.
db.unicorns.find(null, {name: 1});
cursor = db.unicorns.find(null, {name: 1});
_id
по умолчанию возвращается всегда. Но мы можем исключить _id
следующим образом: {name:1, _id: 0}
.
Получаем все поля, кроме поля name
:
db.unicorns.find({}, {name: 0})
Как уже упоминалось, результатом find
является курсор. Поэтому мы можем присоединить к нему ряд методов:
Сортировка (метод sort)
Синтаксис метода sort:
мы указываем поля, по которым надо сортировать, используя 1
для сортировки по возрастанию и -1
для сортировки по убыванию. Например:
db.unicorns.find().sort({weight: -1})
// по убыванию 999,998,997 ...
db.unicorns.find({}, {name: true}).sort({name: -1})
Но для сортировки большого объема данных в Mongo необходимо использовать индексы.
Метод limit()
db.unicorns.find({}, {name: true}).sort({name: -1}).limit(3)
Метод skip()
Метод skip()
позволяет пропустить определенное количество записей.
db.unicorns.find({}, {name: true}).sort({name: -1}).limit(3).skip(1)
Обратите внимание как мы соединяем методы в цепочки.
Моделирование данных
MongoDB не поддерживает JOIN
. По существу мы должны делать второй запрос, чтобы найти связанные данные.
p.s: Для создания нового ObjectID
используется следующий код: NewObjectId = ObjectId()
Когда требуется смоделировать отношения «один-ко-многим» или «многие-ко-многим» можно использовать массивы ( в MongoDB массивы это объекты первого класса).
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d733"), name: 'Siona', manager: [ObjectId("4d85c7039ab0fd70a117d730"), ObjectId("4d85c7039ab0fd70a117d732")] })
При этом данный find
сработает:
db.employees.find({manager: ObjectId("4d85c7039ab0fd70a117d730")})
Массивы значений намного удобнее в использовании, нежели таблицы связи «многие-ко-многим»
Вложенные документы
MongoDB поддерживает вложенные документы:
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d734"), name: 'Ghanima', family: {mother: 'Chani', father: 'Paul', brother: ObjectId("4d85c7039ab0fd70a117d730")}})
Вложенные документы можно запрашивать с помощью точечной нотации:
db.employees.find({'family.mother': 'Chani'})
Денормализация
Традиционный путь ассоциировать пользователя с его постом — это колонка userid
в таблице posts
. С такой моделью нельзя отобразить список постов без дополнительного извлечения данных (JOIN) из таблицы пользователей. Возможное решение — хранить имя пользователя (name
) вместе с userid
для каждого поста.
Команды (выжимка)
db.version()
//показывает номер версии сервера
db.getCollectionNames()
//получить список коллекций внутри нашей БД
db.unicorns.find()
//вернет список документов (записей)
db.unicorns.remove()
//поскольку мы не передали селектора, произойдёт удаление всех документов
//Например, чтобы получить всех самцов единорога, весящих более 700 фунтов, мы можем написать:
db.unicorns.find({gender: 'm', weight: {$gt: 700}})
//Оператор $exists используется для проверки наличия или отсутствия поля, например:
db.unicorns.find({vampires: {$exists: false}})
//Оператор $or используется как ИЛИ
db.unicorns.find({gender: 'f', $or: [{loves: 'apple'}, {loves: 'orange'}, {weight: {$lt: 500}}]})
//update принимает 2 аргумента: селектор (where) для выборки и то, чем обновить соответствующее поле.
//Второй параметр используется для полной замены оригинала
db.unicorns.update({name: 'Roooooodles'}, {weight: 590})
//Модификатор $set обновляет конкретные поля, а не весь документ
db.unicorns.update({name: 'Roooooodles'}, {$set: {weight: 590}})
//модификатор $inc - увеличить или уменьшить значение поля
db.unicorns.update({name: 'Pilot'}, {$inc: {vampires: -2}})
//модификатор $push - позволяет добавить данные в массив
db.unicorns.update({name: 'Aurora'}, {$push: {loves: 'sugar'}})
//Обновление/вставка обновляет документ, если он найден, или создаёт новый — если не найден.
//Чтобы разрешить вставку при обновлении, установите третий параметр в true (ниже мы создаем коллекцию hits, если ее нет)
db.hits.update({page: 'unicorns'}, {$inc: {hits: 1}}, true);
//если установить 4-й параметр в true, то обновятся все документы
db.unicorns.update({}, {$set: {vaccinated: true }}, false, true);
//Второй необязательный параметр у find указывает на список полей, которые мы хотим получить.
db.unicorns.find(null, { name:true })
//получаем все поля, кроме поля name:
db.unicorns.find({}, {name: 0})
//сортировка по убыванию
db.unicorns.find().sort({weight: -1})
// сортируем по весу, но получаем 2 и 3 по весу единорога, пропуская 1-го
db.unicorns.find().sort({weight: -1}).limit(2).skip(1)
//подсчитать кол-во единорогов на счету которых более 60 вампиров
db.unicorns.count({vampires: {$gt: 50}})
//Когда требуется смоделировать отношения «один-ко-многим» или «многие-ко-многим» можно использовать массивы
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d733"), name: 'Siona', manager: [ObjectId("4d85c7039ab0fd70a117d730"), ObjectId("4d85c7039ab0fd70a117d732")] })
// Ищем значение в массиве manager
db.employees.find({manager: ObjectId("4d85c7039ab0fd70a117d730")})
//MongoDB поддерживает вложенные документы:
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d734"), name: 'Ghanima', family: {mother: 'Chani', father: 'Paul', brother: ObjectId("4d85c7039ab0fd70a117d730")}})
//Вложенные документы можно запрашивать с помощью точечной нотации:
db.employees.find({'family.mother': 'Chani'})
// версия > 3.2
db.employees.updateOne(…);
db.employees.updateMany (…);
operator update (документация)
Подключение mongoDB в nodejs
// Retrieve
var MongoClient = require('mongodb').MongoClient;
// Connect to the db
MongoClient.connect("mongodb://localhost:27017/exampleDb", function(err, db) {
if(!err) {
console.log("We are connected");
}
});
Mongoose
ODM – Object-Document Mapper (объектно-документное отображение). У mongo нет жесткой структуры, а вот Mongoose позволяет нам ввести понятие схемы.
Установка и подключение
//install
$ npm install mongoose
//use
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
// connect
});
Схема
Схема в Mongoose определяет метаданные модели — ее свойства, типы данных и ряд другой информации.
mongoosejs.com/docs/guide.html
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
// внутри перечисляем наши поля
var blogSchema = new Schema({
title: String,
author: String,
body: String,
comments: [{ body: String, date: Date }],
date: {
type: Date,
default: Date.now,
required: [true, 'Укажите дату']
},
hidden: Boolean,
meta: {
votes: Number,
favs: Number
}
});
var Blog = mongoose.model('Blog', blogSchema);
// ready to go!
Типы схем
mongoosejs.com/docs/schematypes.html
Модель
http://mongoosejs.com/docs/models.html Модели — это конструкторы, составленные из определения нашей схемы. Экземпляры модели представляют собой документы, которые могут быть сохранены и извлечены из нашей БД.
var schema = new mongoose.Schema({ name: 'string', size: 'string' });
var Tank = mongoose.model('Tank', schema);
Первый параметр в методе mongoose.model указывает на название модели, а второй параметр — собственно схема.
Поиск
http://mongoosejs.com/docs/queries.html
var Person = mongoose.model('Person', yourSchema);
// { 'name.last': 'Ghost' } - условие
// 'name occupation' - выбираем нужные поля
// function (err, person) { ... - обрабатываем данные в callback'е
// find each person with a last name matching 'Ghost', selecting the `name` and `occupation` fields
Person.findOne({ 'name.last': 'Ghost' }, 'name occupation', function (err, person) {
if (err) return handleError(err);
console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation)
// Space Ghost is a talk show host.
})
// находим все
Person.find({ 'name.last': 'Ghost' }, 'name occupation', function (err, docs) {})
// альтернатива callback
Person.find({ 'name.last': 'Ghost' }, 'name occupation').exec(function (err, docs) {})
Сохраняем объект в БД
var Person = mongoose.model('Person', yourSchema);
var subject = new Person({name: 'John'});
subject.save(function(err) {
if (err) return handkeError(err);
})
//или
Person.create({name: 'John'}, function(err, subject) {
if (err) return handkeError(err);
})
Редактирование и удаление
// меняем Karl на Johny
var query = {name: 'Karl'};
Model.update(query, {name: 'Johny'}, options, callback); // все заменит на {name: 'Johny'}
Model.update(query, {$set: {name: 'Johny'}}, options, callback); // меняем только поле name
Person.findOne({name: 'Johny'}, function (err, person) {
if (err) return handleError(err);
person.name = 'Johny';
person.save();
})
//удаление:
Model.remove({name: 'Johny'}, function (err, person) {
if (err) return handleError(err);
})
С mongo можно использовать Promise от node.
mlab.com
mlab.com — это облачный сервис по предоставлению БД mongoDB.
- Создаем БД
- Добавляем пользователя
- И подключаемся в своем приложении:
mongoose
.connect(`mongodb://user_name:pass@ds147072.mlab.com:47072/name_bd`);
CRUD
CRUD — (create, read, update, delete — «создание, чтение,обновление, удаление») — 4 основные функции, используемые при работе базами данных.p.s.
node, а значит и mongo, применяется для высоконагруженных проектов, там, где необходимо передавать много информации, чаты, игры.