能否在Django项目中直接将Elasticsearch作为主数据库使用?
在Django中将Elasticsearch作为主数据库的实现方案
虽然现有资料大多将Elasticsearch作为关系型数据库的搜索引擎增强工具,但确实可以将它作为Django项目的主数据库,以下是可行的实现方式:
基于第三方库改造CRUD逻辑
借助django-elasticsearch-dsl或elasticsearch-dsl-py,可以将Django模型的操作直接映射到Elasticsearch索引。核心是重写模型的核心方法,绕过默认的关系型数据库操作:- 定义Django模型时设置
managed = False,避免生成数据库表 - 用
elasticsearch-dsl的Document类定义ES索引结构,与Django模型字段对应 - 重写模型的
save()、delete()以及查询方法,直接操作ES
示例代码:
from django.db import models from elasticsearch_dsl import Document, Text, Integer from elasticsearch_dsl.connections import connections # 初始化ES连接 connections.create_connection(hosts=['localhost:9200']) # 定义ES文档结构 class UserDocument(Document): name = Text(fields={'keyword': Text()}) age = Integer() class Index: name = 'user_index' settings = { 'number_of_shards': 1, 'number_of_replicas': 0 } # 定义Django模型 class User(models.Model): name = models.CharField(max_length=100) age = models.IntegerField() class Meta: managed = False # 禁止Django自动创建数据库表 def save(self, *args, **kwargs): # 将数据写入ES user_doc = UserDocument( meta={'id': self.id}, name=self.name, age=self.age ) user_doc.save() return super().save(*args, **kwargs) def delete(self, *args, **kwargs): # 从ES删除数据 UserDocument.get(id=self.id).delete() return super().delete(*args, **kwargs) @classmethod def get_by_id(cls, user_id): # 从ES读取数据并封装为Django模型实例 doc = UserDocument.get(id=user_id) return cls(id=doc.meta.id, name=doc.name, age=doc.age)- 定义Django模型时设置
自定义Django数据库后端
如果需要完全兼容Django ORM的查询语法(如filter()、exclude()),可以自定义数据库后端。这需要实现BaseDatabaseWrapper、BaseDatabaseOperations等核心类,将Django的ORM查询转换为Elasticsearch的DSL查询。这种方式复杂度较高,但能实现无缝的ORM体验。关键注意事项
- Elasticsearch不支持事务,如果业务依赖事务回滚等特性,不适合做主数据库
- ES索引默认有1秒的刷新延迟,实时性要求高的场景需调整
refresh_interval参数为-1(手动刷新)或0(实时刷新,性能会受影响) - 长期使用需做好ES的分片管理、快照备份,避免数据丢失
内容的提问来源于stack exchange,提问作者Pragya Bopche
相关产品推荐
相关产品推荐

