building django search app with elasticsearch-7

created at 03-02-2021 views: 6

elasticsearch is powerful, however, django-haystack only supports old versions of elasticsearch.

if we want to use elastic search in our django project, we need to integrate by ourselves.

install java

we first need to check if Java is intalled in our environment:

java -version

you may see results like:

openjdk version "1.8.0_282"
OpenJDK Runtime Environment (build 1.8.0_282-b08)
OpenJDK 64-Bit Server VM (build 25.282-b08, mixed mode)

if not installed, you can easily install Java by:

yum install java

install elasticsearch-7

we'd better install elastchsearch with an user rather than root in our OS

for Linux:

first switch to a user (rather than root):

# /home
[root@localhost home] su - [user]

download

[user@localhost ~] curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.10.1-linux-x86_64.tar.gz

extract

[user@localhost ~] tar -xvf elasticsearch-7.10.1-linux-x86_64.tar.gz

other OS check: here

now the installation is done, we can start elasticsearch-7 now:

[user@localhost ~]$ cd elasticsearch-7.10.1/bin
[user@localhost ~]$ ./elasticsearch

wait for several seconds, we can check whether elasticsearch is runing by commond:

[user@localhost ~]$ curl http://localhost:9200
  • 9200 is  elasticsearch's default port

and if you see something like:

{
  "name" : "iZj6c4tgce8abugvzaupm7Z",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "zKc-YBChQg-vM5Rjm_Ku6g",
  "version" : {
    "number" : "7.10.1",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "1c34507e66d7db1211f66f3513706fdf548736aa",
    "build_date" : "2020-12-05T01:00:33.671820Z",
    "build_snapshot" : false,
    "lucene_version" : "8.7.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

which means elasticsearch is running.

install django-elasticsearch-dsl

Django Elasticsearch DSL is a package that allows indexing of django models in elasticsearch. to install this package:

pip install django-elasticsearch-dsl

django part: create search app

Finally we are able to turn to our django project. We now need to create a search app:

# in directory where manage.py locates

python3 manage.py startapp search

structure of search app:

    ├── blog
    .....
    ├── search
    │   ├── apps.py
    │   ├── documents.py
    │   ├── __init__.py
    │   ├── urls.py
    │   └── views.py

you can add files above manually.

apps.py:

from django.apps import AppConfig

class SearchConfig(AppConfig):
    name = 'workflow.search'

add "workflow.search.apps.SearchConfig" to INSTALLED_APPS in setting.py

urls.py:

from django.urls import path
from workflow.search import views

app_name = "search"

urlpatterns = [
    path('', views.search, name='search'),
]

add url path to the main urls.py:

 ...
 path('search/', include('workflow.search.urls', namespace='search')),
 ...

documents.py

from django_elasticsearch_dsl import Document 
from django_elasticsearch_dsl.registries import registry


from workflow.blog.models import Blog

@registry.register_document
class BlogDocument(Document):
    class Index:
        name = 'blogs'
        settings = {'number_of_shards': 1, 'number_of_replicas': 0}

    class Django:
        model = Blog

        fields = [
            'slug',
            'title',
            'content'
        ]

views.py

from workflow.search.documents import BlogDocument
from django.shortcuts import render


def search(request):
    query = request.GET.get('q')

    sqs_blog = BlogDocument.search().query("multi_match", query=query, fields=["title", "content"])


    blogs = sqs_blog.to_queryset()

    return render(request, 'search/search.html', {'blogs': blogs})

reference

rebuild search index

# in directory where manage.py locates

python3 manage.py search_index --rebuild

show search results

now you can show search results in you django templates as below:

 {% for blog in blogs %}
     {{ blog.title }}
     {{ blog.content }}
     ...etc
 {% endfor %}
Please log in to leave a comment.