Пользователи ищут товары в интернет-магазине, ищут артикулы; поиск является неотъемлемой частью сайта.
Быстрый и гибкий поиск сложно реализовать с помощью реляционных баз данных.
Для таких задач используются поисковые системы, одна из которых Эластичный поиск .
Elasticsearch хорошо документирован и доступен на AWS «из коробки».
Библиотека используется для работы с elasticsearch. elasticsearch-py или elasticsearch-dsl-py .
elasticsearch-dsl-py — это расширенный набор elasticsearch-py, он прост в использовании и поддерживает elasticsearch версии 5.x. На основе этой библиотеки была создана библиотека Джанго-рест-elasticsearch , в основе которого лежит идеология существующего поиска в REST-фреймворк Джанго .
Ниже я подробно опишу, как реализовать поиск в Django REST Framework с помощью elasticsearch с использованием этой библиотеки.
В качестве примера рассмотрим реализацию простого блога с фильтрацией по тегам и поиском по заголовкам статей.
Монтаж
Процесс установки elasticsearch и django подробно описан в официальной документации.Установить пакет довольно просто.
pip install django-rest-elasticsearch
Создание модели и индекса
Давайте создадим модель 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
После создания модели мы опишем нашу модель в виде документа elasticsearch.
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'
Теперь вы можете создать индекс в elasticsearch.
BlogIndex.init()
Автоматическое обновление документов в elasticsearch
После создания модели и индекса нам нужно, чтобы любые изменения в нашей модели были отражены в elasticsearch. Лучший способ сделать это — добавить сигнал Django, который будет отправлять уведомления при возникновении изменений в модели.
Прежде чем создавать сигнал, давайте создадим сериализатор для преобразования объекта django в документ elasticsearch. 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')
Теперь добавим сигнал 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)
После добавления сигнала любые изменения в модели будут мгновенно внесены в elasticsearch.
Создание представления
Приступим к созданию представления для поиска и фильтрации.
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',
)
Вот и все, ищите примеры 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
Полный пример кода доступен по адресу github .
Надеюсь, статья поможет вам реализовать поиск в вашем проекте.
Теги: #django #django rest framework #elasticsearch #python #django
-
Художник Уличной Живописи
19 Oct, 24 -
Ipad Против Интернет-Планшета Archos
19 Oct, 24