Это вторая часть из цикла статей про python и NoSQL (первая - про redis).
Теория
MongoDB один из представителей класса NoSQL (Not Only SQL), относится к документно-ориентированным базам данных с не фиксированной схемой данных. Проект является open-source и написан на C++. Для обмена данными с клиентом используется JSON, а данные хранятся в двоичном формате BSON.
Основной структурной единицей в MongoDB есть документ - упорядоченный набор ключей с связанными значениями. Документы в MongoDB представлены абстрактным типом данных, а конкретная реализация зависит от используемого драйвера. Сами документы хранятся в BJON, бинарном формате, который может хранить документы, как последовательность байтов. Пример представление документа на JavaScript*, в виде объекта:
{"firstword" : "Hello world!"}
MongoDB поддерживает шесть типов данных (null, boolean, numeric, string, array и object.) и является type-sensitive и case-sensitive.
В иерархии структур данных, в MongoDB, над документами находятся - коллекции, которые представляют собой группы документов. Если провести аналогию с таблицами в реляционных БД, то документы будут рядами, а коллекции - таблицами.
Существуют некоторые ограничения в MongoDB: за раз можно вставить 16MB данных, размер документов не может превышать 4MB, размер данных для 32-битной версии mongod ограничен до ~2.5 GB.
В качестве storage engine в MongoDB используется memory-mapped file (отображение файла на память) со всеми вытекающими отсюда плюсами и минусами. MongoDB не подвержен атакам типа инъекции (injection attacks), т.к. не выполняет никакого кода при инсертах.
Еще про теоретическую часть о MongoDB:
Сравнение с другими типами БД:
Нагрузочное тестирование есть тут. Список компаний, использующих MongoDB в продакшене.
Пощупать MongoDB можно на try.mongodb.org, а тут есть cheat sheet по командам.
Установка
Установим MongoDB на Ubuntu. Описание установки на Centos/Fedora/RedHat есть тут.
Берем последнюю стабильную версию отсюда.
wget http://fastdl.mongodb.org/linux/mongodb-linux-i686-1.6.3.tgz
Распаковываем:
tar -xvf mongodb-linux-i686-1.6.3.tgz -C /opt/
Создадим папку для данных и файл для логов
sudo mkdir /var/lib/mongodb/ sudo chown `id -u` /var/lib/mongodb/ sudo touch /var/log/mongodb.log sudo chown `id -u` /var/log/mongodb.log
Создадим конфигурационный файл для mongod
sudo vim /etc/mongod.conf
и запишем в него
port = 5586 fork = true # daemonize it! logpath = /var/log/mongodb.log dbpath = /var/lib/mongodb/
теперь создадим скрипт для запуска mongod с выше определенными параметрами
sudo vim /usr/bin/mongod
и запишем в него
/opt/mongodb-linux-i686-1.6.3/bin/mongod --config /etc/mongod.conf
настроем права
sudo chown `id -u` /usr/bin/mongod sudo chmod ug+x /usr/bin/mongod sudo chown `id -u` /etc/mongod.conf
Все, можно запускать демон с помощью mongod.
Запустим shell и попробую что-то сделать:
/opt/mongodb-linux-i686-1.6.3/bin/mongo --port 5586 > db.test.save({message:'mongodb'}) > db.test.save({message:'nosql'}) > db.test.find() { "_id" : ObjectId("4cdeadbd637b7e915544335a"), "message" : "mongodb" } { "_id" : ObjectId("4cdeadc3637b7e915544335b"), "message" : "nosql" }
Использование с Python
Для работы Python с MongoDB существует базовый модуль pymongo (документация). На базе pymongo построены два известных ODM: mongokit и mongoengine. Хорошие сравнение mongokit vs mongoengine есть тут. Еще один ODM - mongoalchemy.
Установим последнюю версию pymongo
pip install pymongo
Для примера возьмем две сущности Киноман и Фильм. Каждый киноман имеет собственную оценку по фильму, посчитаем (с помощью map/reduce) среднюю оценку по фильму.
# coding=utf-8 from pymongo import Connection from pymongo.code import Code # создадим соединение connection = Connection('localhost', 5586) # очистим БД connection.drop_database('cinephiles') # создадим БД db = connection.cinephiles # создадим коллекции для films и users films = db.films users = db.users # создадим новые документы с данными о сущности 'Фильм' films.insert([{'_id':1, 'title':'The Expendables', 'release':2010}, {'_id':2, 'title':'Iron Man 2', 'release':2010}, {'_id':3, 'title':'Prince of Persia', 'release':2010}]) # выведем список со всеми фильмами for film in films.find(): print film # создадим новые документы с данными о сущности 'Киноман' users.insert({'name': 'John', 'films':[{'film':1, 'mark':3}, {'film':2, 'mark':5}, {'film':3, 'mark':5}]}) users.insert({'name': 'Jane', 'films':[{'film':1, 'mark':4}, {'film':2, 'mark':3}, {'film':3, 'mark':5}]}) users.insert({'name': 'Sali', 'films':[{'film':1, 'mark':5}, {'film':2, 'mark':2}, {'film':3, 'mark':5}]}) # посчитаем всех киноманов film_count = films.count() # подготовим данные для подсчета map = Code(""" function() { this.films.forEach( function(x) { emit(x.film, x.mark); } ); }""") # посчитаем среднюю оценку по фильму reduce = Code("""function (key, values) { var sum = 0; for(var mark in values) sum += values[mark]; return sum/%d; }""" % film_count) # выведем среднюю оценку по каждому фильму result = db.users.map_reduce(map, reduce) for mark in result.find(): print mark
Результат:
{u'release': 2010, u'_id': 1, u'title': u'The Expendables'} {u'release': 2010, u'_id': 2, u'title': u'Iron Man 2'} {u'release': 2010, u'_id': 3, u'title': u'Prince of Persia'} {u'_id': 1.0, u'value': 1.3333333333333333} {u'_id': 2.0, u'value': 1.1111111111111112} {u'_id': 3.0, u'value': 1.6666666666666667}
Еще хороший пример с методами pymongo есть тут.
Использование с Django
Этот раздел тут упомяну лишь вскользь, более полный вариант будет в будущей заметке.
Мониторинг и администрирование
По-умолчанию с mongod стартует простой http-сервер, по тому же адресу что и сам mongod но порт на 1000 больше, чем порт самого mongod. Этот сервер предоставляет http интерфейс для просмотра базовой информации о сервере MongoDB. Вся представленная информация в простом веб-интерфейсе также может быть получена через shell, например текущую версию сервера, uptime и количество подключений можно узнать с помощью:
> db.runCommand({"serverStatus" : 1})
В базовой поставкой MongoDB есть консольная-команда mongostat - выводит ту же инфу что и serverStatus, но в более дружественном виде.
Для web-админимтрирования MongoDB есть Opricot, подробнее можете прочитать на домашней странице.
Репликации
Другие применения MongoDB
Map Reduce
Дополнительно чтиво