📜 ⬆️ ⬇️

Search in the Django REST Framework using Elasticsearch

Users search for products in the online store, search for articles, search is an integral component of the site. Fast and flexible search is difficult to implement with relational databases. For such tasks use search engines, one of which is Elasticsearch . Elasticsearch is well documented and available out of the box on AWS.


To work with elasticsearch, the library uses elasticsearch-py or elasticsearch-dsl-py . elasticsearch-dsl-py is an add-on over elasticsearch-py, it is easy to use and supports version 5.x elasticsearch. Based on this library, the django-rest-elasticsearch library was created, which is based on the ideology of the existing search in the Django REST Framework . Below I will describe in detail how to implement a search in the Django REST Framework using elasticsearch using this library.



As an example, consider the implementation of a simple blog with filtering by tags and search by article title.


Installation


The installation process of elasticsearch and django is detailed in the official documentation. With the installation package everything is quite simple


pip install django-rest-elasticsearch 

Creating a model and index


Create a model


 class Blog(models.Model): title = models.CharField(_('Title'), max_length=1000) created_at = models.DateTimeField(_('Created at'), auto_now_add=True) body = models.TextField(_('Body')) tags = ArrayField(models.CharField(max_length=200), blank=True, null=True) is_published = models.BooleanField(_('Is published'), default=False) def __str__(self): return self.title 

After creating the model, we will describe our model as an elasticsearch document.


 class BlogIndex(DocType): pk = Integer() title = Text(fields={'raw': Keyword()}) created_at = Date() body = Text() tags = Keyword(multi=True) is_published = Boolean() class Meta: index = 'blog' 

Now you can create an index in elasticsearch


 BlogIndex.init() 

Automatic update of documents in elasticsearch


After creating the model and the index, it is necessary that any changes in our model are displayed in elasticsearch. The best way to do this is to add a django signal that will send notifications when changes occur in the model. Before creating a signal, create a serializer for converting a django object into an elasticsearch document


 from rest_framework_elasticsearch.es_serializer import ElasticModelSerializer from .models import Blog from .search_indexes import BlogIndex class ElasticBlogSerializer(ElasticModelSerializer): class Meta: model = Blog es_model = BlogIndex fields = ('pk', 'title', 'created_at', 'tags', 'body', 'is_published') 

Now add a signal


 from django.db.models.signals import pre_save, post_delete from django.dispatch import receiver from .serializers import Blog, ElasticBlogSerializer @receiver(pre_save, sender=Blog, dispatch_uid="update_record") def update_es_record(sender, instance, **kwargs): obj = ElasticBlogSerializer(instance) obj.save() @receiver(post_delete, sender=Blog, dispatch_uid="delete_record") def delete_es_record(sender, instance, *args, **kwargs): obj = ElasticBlogSerializer(instance) obj.delete(ignore=404) 

After adding a signal, any changes in the model will be instantly made in elasticsearch


Create view


Let's start creating a view for searching and filtering.


 from elasticsearch import Elasticsearch, RequestsHttpConnection from rest_framework_elasticsearch import es_views, es_filters from .search_indexes import BlogIndex class BlogView(es_views.ListElasticAPIView): es_client = Elasticsearch(hosts=['elasticsearch:9200/'], connection_class=RequestsHttpConnection) es_model = BlogIndex es_filter_backends = ( es_filters.ElasticFieldsFilter, es_filters.ElasticSearchFilter ) es_filter_fields = ( es_filters.ESFieldFilter('tag', 'tags'), ) es_search_fields = ( 'tags', 'title', ) 

That's all, search examples


 http://example.com/blogs/api/list?search=elasticsearch http://example.com/blogs/api/list?tag=opensource http://example.com/blogs/api/list?tag=opensource,aws 

The full sample code is available on github . I hope that the article will help you implement the search in your project.


')

Source: https://habr.com/ru/post/327694/


All Articles