混合 PostgreSQL 和 MongoDB(作为 Django 后端)

2022-01-13 00:00:00 python postgresql django mongodb nosql

问题描述

出于性能原因,我正在考虑将我的网站后端从 Postgres 转移到 Mongo,但该网站的关键部分依赖 GeoDjango 模型来计算现实世界中对象之间的距离(等等).

I'm thinking about shifting my site's backend to Mongo from Postgres for performance reasons, but key parts of the site rely on the GeoDjango models to calculate distances between objects in the real world (and so on).

让大部分站点在 Mongo 上运行但那些关键区域使用 Postgres 进行存储是否可行?这是痛苦的和/或容易出错的吗?是否有我缺少的全 Mongo 解决方案?

Would it be feasible to have most of the site running on Mongo but those key areas using Postgres for storage? Is this painful and / or error-prone? Is there an all-Mongo solution I'm missing?

如果您能为我提供关于这些问题的任何启示,我们将不胜感激.

Any light you can shed on these matters for me would be much appreciated.


解决方案

从Django 1.2开始,你可以在您的 settings.py 中定义多个数据库连接.然后你可以使用数据库路由器 告诉 Django 去哪个数据库,对你的应用程序透明.

Since Django 1.2, you can define multiple datbase connections in your settings.py. Then you can use database routers to tell Django which database to go to, transparently for your application.

免责声明:这就是我认为应该如何工作的方式,我从未在 Django 中使用过 MongoDB,也没有测试过我的代码是否真的有效.:)

Disclaimer: this is how I think it should work, I have never used MongoDB in Django, nor have I tested that my code actually works. :)

DATABASES = {
    'default': {
        'ENGINE': 'django_mongodb_engine',
        'NAME': 'mydata',
        ...
    }
    'geodata' {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'geodata',
        ...
    }
}

DATABASE_ROUTERS = ['path.to.ModelMetaRouter']

型号

然后将自定义元变量添加到您的地理表中,以覆盖其数据库.不要将此属性添加到应该转到默认数据库的模型中.

Models

Then add custom Meta variables to your geo-tables, to override their database. Don't add this attribute to models that are supposed to go to the default database.

class SomeGeoModel(models.Model):
    ...
    class Meta:
        using = 'geodata'

数据库路由器

并编写一个数据库路由器来将所有具有 using 元属性集的模型定向到适当的连接:

Database router

And write a database router to direct all models that have the using meta attribute set, to the appropriate connection:

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

相关文章