【问题标题】:How to sync postgres database with neo4j in realtime while using Django-admin?如何在使用 Django-admin 时将 postgres 数据库与 neo4j 实时同步?
【发布时间】:2021-07-17 16:31:54
【问题描述】:

所以目前我正在开发一个 Django 项目,其中有两个不同的数据库。一个是 PostgreSQL,第二个是 Neo4j。我想要的是两个数据库之间的实时同步。我正在使用 Django-admin 面板在 Postgres 数据库中进行 crud 操作。现在我也想更新 neo4j 数据库中的每个 crud 操作。但我不知道该怎么做。

【问题讨论】:

    标签: django database postgresql neo4j django-admin


    【解决方案1】:

    您可以选择几条路线。我认为您将希望将 Postgres 作为您的主要 Django 数据库并使用 Neo4j 作为辅助数据库,而不是由 Django 框架管理。您可以通过使用类似于this post 的 Neo4j 客户端库来自己与图形数据库进行交互来做到这一点。

    为了让 Neo4j 与 Django 管理的 Postgres 保持同步,我认为 signals 将成为你最好的朋友,特别是 post_save 信号。本质上,每当您保存 Django 模型时,此信号都会触发一个函数,您可以编写该函数以使用 Neo4j 客户端 API 反映图形数据库中的更改。

    但是,根据您的模型的复杂程度,确定哪些字段已更改以仅更新这些字段可能会变得很棘手。不久前我遇到了类似的问题,并使用了这个自定义 Mixin(我找不到原作者,但把它保存在我的笔记中):

    from django.forms import model_to_dict
    import logging
    
    logger = logging.getLogger(__name__)
    
    
    class ModelDiffMixin(object):
        """
        A model mixin that tracks model fields' values and provide some useful api
        to know what fields have been changed.
        """
    
        def __init__(self, *args, **kwargs):
            super(ModelDiffMixin, self).__init__(*args, **kwargs)
            self.__initial = self._dict
    
        @property
        def diff(self):
            d1 = self.__initial
            d2 = self._dict
            diffs = [(k, (v, d2[k])) for k, v in d1.items() if v != d2[k]]
            return dict(diffs)
    
        @property
        def has_changed(self):
            return bool(self.diff)
    
        @property
        def changed_fields(self):
            return self.diff.keys()
    
        def get_field_diff(self, field_name):
            """
            Returns a diff for field if it's changed and None otherwise.
            """
            return self.diff.get(field_name, None)
    
        def save(self, *args, **kwargs):
            """
            Saves model and set initial state.
            """
            super(ModelDiffMixin, self).save(*args, **kwargs)
            self.__initial = self._dict
    
        @property
        def _dict(self):
            return model_to_dict(self, fields=[field.name for field in
                                 self._meta.fields])
    
    
    

    如果你在你的模型中实现了这个 Mixin 以与 Neo4j 同步,那么在post_save 信号处理程序中你可以调用model.diffmodel.changed_fields 来查看哪些属性需要在 Neo4j 节点上更新,而不是删除整个节点并重新创建它和所有关系。

    【讨论】:

    • 感谢您的回答。你的回答完全正确。但当时当我被问到问题时,我对信号没有广泛的了解。在我知道信号后,我使用所有信号方法解决了我的问题。
    猜你喜欢
    • 2020-03-13
    • 1970-01-01
    • 1970-01-01
    • 2021-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-13
    相关资源
    最近更新 更多