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

发布于 2024-11-02 20:11:03 字数 203 浏览 1 评论 0原文

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

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

如果您能为我解答这些问题,我将不胜感激。

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).

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

Hello爱情风 2024-11-09 20:11:03

从 Django 1.2 开始,您可以在设置中定义多个数据库连接。 py.然后您可以使用数据库路由器 告诉 Django 要访问哪个数据库,这对您的应用程序来说是透明的。

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

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'

数据库路由器

并编写一个数据库路由器,将所有设置了 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

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.

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. :)

settings.py

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'

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
素罗衫 2024-11-09 20:11:03

元列表中不能有“使用”。

这是一个可行的解决方案

,将其添加到 models.py:

 import django.db.models.options as options
 options.DEFAULT_NAMES = options.DEFAULT_NAMES + ('in_db',)

在您的应用程序文件夹中创建一个 router.py:router.py

myapp folder content:
   models.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']

you can't have 'using' in the Meta list.

here is a working solution

add this to models.py:

 import django.db.models.options as options
 options.DEFAULT_NAMES = options.DEFAULT_NAMES + ('in_db',)

create a router.py in your apps folder:

myapp folder content:
   models.py
   router.py
   ...

Content of 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

Reference router in your settings:

   DATABASE_ROUTERS = ['myapp.router.ModelMetaRouter']
情定在深秋 2024-11-09 20:11:03

我会看一下 Disqus talk from DjangoCan 2010 关于它们的缩放建筑学。他们很可能在 Postgres 上运行最大的 Django 网站。他们提供了简单的代码片段,展示了如何使用 Django 内置功能启动垂直和水平缩放。

我的理解是,他们确实使用 MongoDB 进行一些分析,但我认为该演讲中没有讨论这一点。

I would take a look at the Disqus talk from DjangoCan 2010 about their scaling architecture. They run quite possibly the largest Django website on top of Postgres. They present simple code snippets showing how to start both vertical and horizontal scaling using features built into Django.

My understanding is that they do use MongoDB for some of their analytics thought I don't think it's discussed in that talk.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文