Открыть меню    

MongoDB Подробное руководство

На сайте dnzl.ruактуальная версия статьи

MongoDB состоит из: БД, которые состоят из коллекций. Коллекции, в свою очередь, состоят из документов. Каждый документ состоит из полей. www.mongodb.com

MongoDB клиенты

  • https://robomongo.org/
  • https://studio3t.com/

Конфиг

В папке 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");
  }
});

соединение с БД mongo DB

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

  • String
  • Number
  • Date
  • Buffer (например, для изображений)
  • Boolean
  • Mixed (любой тип данных)
  • Objectid
  • Array

    Модель

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, применяется для высоконагруженных проектов, там, где необходимо передавать много информации, чаты, игры.

На сайте dnzl.ruактуальная версия статьи

Комментарии к статье