Integrate ElasticSearch with Django
Start an elasticsearch docker container
cd ~/mdblogcd into /path/to/django-project/base_dirtouch compose.yaml
@compose.yaml
services:
elasticsearch:
container_name: elasticsearch
image: docker.elastic.co/elasticsearch/elasticsearch:8.13.0
volumes:
- esdata01:/usr/share/elasticsearch/data
ports:
- 9200:9200
environment:
- discovery.type=single-node
- xpack.security.enabled=false
volumes:
esdata01:
docker compose up -dcurl localhost:9200to test if the elasticsearch instance is running
Config Django Project
pip install django-elasticsearch-dsl
@settings.py
......
INSTALLED_APPS = [
......
'django_elasticsearch_dsl',
......
]
......
ELASTICSEARCH_DSL = {
'default': {
'hosts': 'http://localhost:9200'
}
}
......
@posts/models.py
......
Class Post(models.Model):
......
content = MDTextField()
......
# MDTextField() can't be processed by ElasticSearch
def type_to_string(self):
"""Convert the type field to its string representation
"""
return str(self.content)
touch posts/documents.pyCreate a documents.py inside a Django app (e.g. named posts)
@posts/documents.py
from django_elasticsearch_dsl import Document, fields
from django_elasticsearch_dsl.registries import registry
from .models import Post
# We need to run 'python manage.py search_index --rebuild' each time after we change something here
@registry.register_document
class PostDocument(Document):
content = fields.TextField(attr="type_to_string")
class Index:
name = 'posts'
settings = {'number_of_shards': 1, 'number_of_replicas': 0}
class Django:
model = Post
fields = ['title', 'created_on', 'slug']
@posts/views.py
......
from .documents import PostDocument
from elasticsearch_dsl.query import MultiMatch
......
class PostListView(ListView):
model = Post
template_name = 'posts/post_list.html'
paginate_by = 10
# Search function
def get_queryset(self):
object_list = super().get_queryset()
q = self.request.GET.get('q')
if q:
# Implement Elastic Search
query = MultiMatch(query=q, fields=['title', 'content'], fuzziness='AUTO')
object_list = PostDocument.search().query(query)
return object_list
- Replace
<a href="{{ post.get_absolute_url }}">with<a href="/post/{{ post.slug }}/">@posts/post_list.html
Reference