基本用法
Django REST Elasticsearch提供了集成Django REST Framework和Elasticsearch的简便方法。该库使用Elasticsearch DSL库(elasticsearch-dsl-py)它是官方低级客户端的高级库。
让我们看一下使用Django REST Elasticsearch构建一个简单应用程序的快速示例。在这个例子中,我们将构建一个简单的博客系统。
要求
- Django REST Framework 3.5及更高版本
- elasticsearch-dsl> = 5.0.0,<7.0.0(Elasticsearch 5.x)
安装
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中创建映射
然后,我们必须围绕我们的Django模型创建一个类似于模型的包装器。
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中创建映射。为此,您可以通过调用init类方法直接创建映射:
BlogIndex.init()
在文档生命周期文档中,您可以找到有关如何手动使用文档的完整说明。
添加,更新或删除新数据时使索引可更新
我们希望在ElasticSearch中拥有一致的数据,这就是我们在更改模型中的任何内容时需要创建,更新或删除文档的原因。最好的方法是添加一个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')
在我们需要创建signals.py文件并添加此代码之后:
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)
简单的django REST框架搜索视图
最后,让我们创建一个简单的搜索视图,查找按标签过滤的所有帖子,并按标题中的单词进行搜索:
from elasticsearch import Elasticsearch, RequestsHttpConnection
from rest_framework_elasticsearch import es_views, es_pagination, 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
分页
分页响应的示例
class BlogView(es_views.ListElasticAPIView):
es_client = Elasticsearch(hosts=['elasticsearch:9200/'],
connection_class=RequestsHttpConnection)
es_pagination_class = es_pagination.ElasticLimitOffsetPagination
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',
)
排序
排序示例
class BlogView(es_views.ListElasticAPIView):
es_client = Elasticsearch(hosts=['elasticsearch:9200/'],
connection_class=RequestsHttpConnection)
es_pagination_class = es_pagination.ElasticLimitOffsetPagination
es_filter_backends = (
es_filters.ElasticFieldsFilter,
es_filters.ElasticSearchFilter,
es_filters.ElasticOrderingFilter,
)
es_ordering_fields = (
"created_at",
("title.raw", "title")
)
es_filter_fields = (
es_filters.ESFieldFilter('tag', 'tags'),
)
es_search_fields = (
'tags',
'title',
)