Бэкапим. База при этом онлайн и обслуживает запросы.
mongodump -o DIR_NAMEВосстанавливаем. База при этом онлайн и обслуживает запросы.
mongorestore DIR_NAME
Пример:
igor@msws:~$ mongodump -o ~/bkp/2012_03_14/ igor@msws:~$ mongorestore ~/bkp/2012_03_14/
Всё
Готова первая версия агрегатора купонов http://otkuponer.ru/ (если не открывается, ждите пока приедут DNS-ы).
Как обычно минимальный дизайн. На текущий момент работает 2 системы купонов(биглион и групон), на подходе купикупон.
Проект выполняется в чистом стиле проектирования по модели предметной области, но без Active Record (ty to CanceRus). Для разработки используется Agile подход.
СУБД юзается MongoDB, программировать мега-приятно (ty to 10gen).
Фреймворк для разработки — старичок CodeIgniter (но по скорости работы он весьма не старичок).
В планах сделать парсеры на 100500 сайтов купонов и что-нить улучшить для посетителей.
В интернетах бытует мнение, что хранить файлы в БД — школоло. Разрушаем стереотип с Mongo GridFS.
Введение:
MongoDB предоставляет возможность хранить файлы любого размера в Mongo GridFS
Для драйвера PHP — это обычная коллекция, в которой есть поле для хранения бинарных данных.
Бинарные данные в свою очередь разбиваются на чунки(небольшие куски).
Бинарные данные можно извлечь как целиком, так и почунково(это экономит память).
Плюсы хранения данных в БД MongoDB:
MongoDB может хранить миллионы файлов в БД, хранение такого объёма данных в файловой системе может вызвать проблемы(начиная с IO проблем, заканчивая проблемами доступа к данным из разных серверов).
MongoDB реплицирует данные на все сервера, что упрощает доступ к данным на отдельно взятом сервере.
Нет проблем с бекапами и целостностью данных на разных серверах. надёжность обеспечивается MongoDB.
К загруженному файлу можно прикрепить метаданные (описание, комментарии, лайки, и.т.д.)
Т.к. файлы хранятся в чунках — можно работать с любой частью файла.
Минусы:
Быстродействие ниже, чем nginx + файловая истема. Сравним:
nginx + файловая система, получаем 6559.31 операций в секунду
apache + файловая система: получаем 2625.37 операций в секунду
nginx + модуль nginx-gridfs, получаем 1083.88 операций в секунду
Вывод: nginx + fs на высоте, но это решение не даёт масштабируемости и гибкости.
nginx + nginx-gridfs даёт приличные результаты, которые существенно возрастут, при использовании нескольких серверов MongoDB.
Благодарность, http://tokarchuk.ru за тесты.
Задача: хранить авторов к публикациям.
Делема: хранить авторов в отдельной коллекции или внутри документа публикации?
Решение #1:
{ "_id" : ObjectId("4dd491695072aefc456c9aca"), "username" : "alphareplicant", "email" : "roybatty@androids.org", "fullname" : "Roy Batty", "joined_at" : ISODate("2011-05-19T03:41:29.703Z"), "address" : { "street" : "13 Tannhauser Gate", "city" : "Caprica", "state" : "CC", "zipcode" : 512 }, }
Решение #2:
{ _id : ObjectId("4dcd2abe5981aec801010000"), title : "The only perfect site is hind-site", content : "Loren ipsum dolor sit amet…", saved_at : ISODate('2011-05-16T18:42:57.949Z'), author_id : ObjectId("4dd491695072aefc456c9aca") }
Так как же поступить?
Этот вопрос всегда возникает, при проектировании способа хранения данных. в nosql решениях.
Решение #1:
Плюсы: данные о авторе доступны в основном документе публикации, что экономит на количестве запросов в базу.
Минусы: Если документы существенно велики, и используется не курсор, а массив, для работы с данными. Можно допустить перерасход памяти.
решение #2:
Плюсы: лёгкие документы
Минусы: дополнительная коллекция, документы которой можно извлечь дополнительным запросом.
Задача: Добавить в коллекцию страниц (pages), документ только в том случае, если ещё нет документов со значением ‘url’ равным вставляемому значению. Избежать дублирования страниц.
Условие: максимально быстро.
Решение:
1. Создаём уникальный индекс на коллекцию. поле ‘url’ с удалением дублирующихся.
2. Делаем bulk insert:
$pages — массив документов, для помещения в колекцию.
‘safe’=>false — игнорировать ошибки операции (в нашем случае, дублирование ‘url’ с документами в коллекции)
//Формируем массив из кучи документов $pages[]=array ( 'url'=>$url, 'site_id'=>$site->_id, 'need_load'=>true ); ... $mongo->pages->batchInsert($pages, array('safe'=>false));
По моим тестам, массив из 10-20 тысяч документов вставляется за пару секунд(думаю вся коллекция находится в памяти, данных не много)
Сегодня 2 весёлых примера.
1. логический или (or).
Задача: Найти пользователей, у которых возраст менее 20 лет, и тех, у которых возраст не заполнен.
Постановка задачи: т.к. mongodb является schema-free СУБД, то наличие нашего поля age не является обязательным. Запрос должен выглядеть(на языке логики) следующим образом: age<20 or age is null
Проблема: на php адаптере mongodb запрос or должен выглядеть следующим образом:
'$or'=>array(условие1, условие2)
При этом:
уловие1 = 'age'=>array('$lte'<=20) уловие2 = 'age'=>array('$exists'=>false)
php, успешно заменит элемент массива с индексом ‘age’ из условие1 на, значение из условие2.
Решение:
завернём условие1 и условие2 в дополнительный массив:
$where=array ( '$or'=>array ( array ( 'age'=>array ( '$lte'=>20, ) ), array ( 'age'=>array ( '$exists'=>false ) ) ) );
Многобуков. Всё под катом.
Допустим у вас есть в коллекции групп массив операций которые входят в группу(также это может быть коллекция постов, в которую входит массив комментариев).
Задача: выдернуть операции, упорядочив их по id.
Черновик решения:
db.runCommand( { mapreduce: operations_groups, map : function Map() { this.operations.forEach ( function(z) { emit( this.id , z); } ); } reduce : function Reduce(key, values) { return {values:values.sort()}; } finalize : function Finalize(key, reduced) { return reduced; } keeptemp : false });