Использование MongoDB в Django

от автора

— документо-ориентированная система управления базами данных (СУБД) с открытым исходным кодом, не требующая описания схемы таблиц. Написана на языке C++ и распространяется в рамках лицензии Creative Commons.

В последнее время становится довольно популярной и восстребованой. И вот возникла идея использовать ее в связке с фреймворком Django. Собственно о чем далее и пойдет речь.

Для решения поставленной задачи мы будем использовать приложение mongodb-engine. Данное приложение тесно связано еще с несколькими приложениями, установкой которых мы и займемся вначале.

Django-nonrel — используется для поддержки NoSQL в Django.

pip install hg+https://bitbucket.org/wkornewald/django-nonrel 

djangotoolbox — набор инструментов для работы с нереляционными базами данных, лишним не будет.

pip install hg+https://bitbucket.org/wkornewald/djangotoolbox 

А теперь уже ставим и mongodb-engine:

pip install git+https://github.com/django-nonrel/mongodb-engine 

Указываем нашу базу данных в settings:

DATABASES = {    'default' : {       'ENGINE' : 'django_mongodb_engine',       'NAME' : 'my_database'    } } 

При необходимости также можно указать host, port, user, password.

Данное приложение предоставляет два типа полей для хранения произвольных данных, не входящих в стандартную django модель.

ListField

Списки и им подобные, представление массивов в формате BSON

from djangotoolbox.fields import ListField  class Post(models.Model):     ...     tags = ListField() 
>>> Post(tags=['django', 'mongodb'], ...).save() >>> Post.objecs.get(...).tags ['django', 'mongodb'] 

Вариант с указанием типа:

class Post(models.Model):     ...     edited_on = ListField(models.DateTimeField()) 
>>> post = Post(edited_on=['1010-10-10 10:10:10']) >>> post.save() >>> Post.objects.get(...).edited_on [datetime.datetime([1010, 10, 10, 10, 10, 10])] 

Данный тип поля удобно использовать для организации связи один-ко-многим:

from djangotoolbox.fields import EmbeddedModelField, ListField  class Post(models.Model):     ...     comments = ListField(EmbeddedModelField('Comment'))  class Comment(models.Model):     ...     text = models.TextField() 

EmbeddedModelField — используется для организации связей между моделями.

DictField

Второй тип поля DictField, который используется в BSON для обьектов.

from djangotoolbox.fields import DictField  class Image(models.Model):     ...     exif = DictField() 
>>> Image(exif=get_exif_data(...), ...).save() >>> Image.objects.get(...).exif {u'camera_model' : 'Spamcams 4242', 'exposure_time' : 0.3, ...} 

Вариант с указанием типа:

class Poll(models.Model):     ...     votes = DictField(models.IntegerField()) 

>>> Poll(votes={'bob' : 3.14, 'alice' : '42'}, ...).save() >>> Poll.objects.get(...).votes {u'bob' : 3, u'alice' : 42} 
Обновление данных
Post.objects.filter(...).update(title='Everything is the same') 

Можно использовать для обновления оператор $set

.update(..., {'$set': {'title': 'Everything is the same'}}) 

А также функцию F()

Post.objects.filter(...).update(visits=F('visits')+1) 

В результате получится что то такое:

.update(..., {'$inc': {'visits': 1}}) 
Использование низко-уровневых запросов

Если Вам не хватает возможностей Django ORM, можно использовать запросы к MongoDB минуя стандартный механизм.

raw_query() — принимает один аргумент, возвращает данные в виде стандартного Django queryset. Что хорошо для дальнейшей обработки данных.

Пример с geo данными, модель:

from djangotoolbox.fields import EmbeddedModelField from django_mongodb_engine.contrib import MongoDBManager  class Point(models.Model):     latitude = models.FloatField()     longtitude = models.FloatField()  class Place(models.Model):     ...     location = EmbeddedModelField(Point)      objects = MongoDBManager() 

получим все точки рядом с конкретными координатами:

>>> here = {'latitude' : 42, 'longtitude' : 3.14} >>> Place.objects.raw_query({'location' : {'$near' : here}}) 

raw_update() — используется если нам недостаточно стандартных средств для обновления данных.

Модель:

from django_mongodb_engine.contrib import MongoDBManager  class FancyNumbers(models.Model):     foo = models.IntegerField()      objects = MongoDBManager() 

использование:

FancyNumbers.objects.raw_update({}, {'$bit' : {'foo' : {'or' : 42}}}) 

В данном примере выполняется побитовое or для каждого foo в базе.

На этом возможности данной связки не заканчиваются, но если пречислять все, то статья не оправдано затянется. Полное описание и примеры можно будет посмотреть по представленным ниже ссылкам.

Ссылки:
MongoDB
mongodb-engine
Пример создания блога
GitHub

ссылка на оригинал статьи http://habrahabr.ru/post/160191/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *