Смешивание PostgreSQL и MongoDB (как бэкэндов Django)
Я думаю о переносе моего сайта на Mongo из Postgres по соображениям производительности, но ключевые части сайта полагаются на модели GeoDjango для расчета расстояний между объектами в реальном мире (и т.д.).
Было бы возможно, чтобы большая часть сайта работала на Mongo, но в тех ключевых областях, которые использовали Postgres для хранения? Является ли это болезненным и/или подверженным ошибкам? Есть ли все-монгольское решение, которое мне не хватает?
Любой свет, который вы можете пролить на эти вопросы для меня, будет очень оценен.
Ответы
Ответ 1
С Django 1.2 вы можете определить несколько подключений datbase в своем settings.py
. Затем вы можете использовать маршрутизаторы баз данных, чтобы сообщить Django, какая база данных будет прозрачной для вашего приложения.
Отказ от ответственности:, как я думаю, он должен работать, я никогда не использовал MongoDB в Django и не проверял, что мой код действительно работает.:)
settings.py
DATABASES = {
'default': {
'ENGINE': 'django_mongodb_engine',
'NAME': 'mydata',
...
}
'geodata' {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'geodata',
...
}
}
DATABASE_ROUTERS = ['path.to.ModelMetaRouter']
Модели
Затем добавьте настраиваемые мета-переменные в ваши геотаблицы, чтобы переопределить их базу данных. Не добавляйте этот атрибут к моделям, которые должны перейти в базу данных по умолчанию.
class SomeGeoModel(models.Model):
...
class Meta:
using = 'geodata'
Маршрутизатор баз данных
И напишите маршрутизатор базы данных, чтобы направить все модели, у которых есть атрибут meta using
, к соответствующему соединению:
class ModelMetaRouter(object):
def db_for_read(self, model, **hints):
return getattr(model._meta, 'using', None)
def db_for_write(self, model, **hints):
return getattr(model._meta, 'using', None)
def allow_relation(self, obj1, obj2, **hints):
# only allow relations within a single database
if getattr(obj1._meta, 'using', None) == getattr(obj2._meta, 'using', None):
return True
return None
def allow_syncdb(self, db, model):
if db == getattr(model._meta, 'using', 'default'):
return True
return None
Ответ 2
вы не можете "использовать" в мета-списке.
здесь находится рабочее решение
Добавьте это в models.py:
import django.db.models.options as options
options.DEFAULT_NAMES = options.DEFAULT_NAMES + ('in_db',)
создайте файл router.py в папке ваших приложений:
myapp folder content:
models.py
router.py
...
Содержимое router.py:
class ModelMetaRouter(object):
def db_for_read(self, model, **hints):
db = getattr(model._meta, 'in_db', None) # use default database for models that dont have 'in_db'
if db:
return db
else:
return 'default'
def db_for_write(self, model, **hints):
db = getattr(model._meta, 'in_db', None)
if db:
return db
else:
return 'default'
def allow_relation(self, obj1, obj2, **hints):
# only allow relations within a single database
if getattr(obj1._meta, 'in_db', None) == getattr(obj2._meta, 'in_db', None):
return True
return None
def allow_syncdb(self, db, model):
if db == getattr(model._meta, 'in_db', 'default'):
return True
return None
Справочный маршрутизатор в ваших настройках:
DATABASE_ROUTERS = ['myapp.router.ModelMetaRouter']
Ответ 3
Я бы рассмотрел Disqus talk из DjangoCan 2010 об их архитектуре масштабирования. Они запускают вполне возможно крупнейший сайт Django поверх Postgres. В них представлены простые фрагменты кода, показывающие, как начинать вертикальное и горизонтальное масштабирование с помощью функций, встроенных в Django.
Я понимаю, что они используют MongoDB для некоторых своих аналитиков, думая, что я не думаю, что это обсуждалось в этом разговоре.