基本用法
Django REST Elasticsearch提供了集成Django REST Framework和Elasticsearch的簡(jiǎn)便方法磷醋。該庫(kù)使用Elasticsearch DSL庫(kù)(elasticsearch-dsl-py)它是官方低級(jí)客戶端的高級(jí)庫(kù)。
讓我們看一下使用Django REST Elasticsearch構(gòu)建一個(gè)簡(jiǎn)單應(yīng)用程序的快速示例胡诗。在這個(gè)例子中邓线,我們將構(gòu)建一個(gè)簡(jiǎn)單的博客系統(tǒng)。
要求
- Django REST Framework 3.5及更高版本
- elasticsearch-dsl> = 5.0.0煌恢,<7.0.0(Elasticsearch 5.x)
安裝
pip install django-rest-elasticsearch
創(chuàng)建模型
首先骇陈,我們創(chuàng)建一個(gè)模型。
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中創(chuàng)建映射
然后瑰抵,我們必須圍繞我們的Django模型創(chuàng)建一個(gè)類似于模型的包裝器你雌。
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中創(chuàng)建映射。為此二汛,您可以通過(guò)調(diào)用init類方法直接創(chuàng)建映射:
BlogIndex.init()
在文檔生命周期文檔中婿崭,您可以找到有關(guān)如何手動(dòng)使用文檔的完整說(shuō)明。
添加肴颊,更新或刪除新數(shù)據(jù)時(shí)使索引可更新
我們希望在ElasticSearch中擁有一致的數(shù)據(jù)氓栈,這就是我們?cè)诟哪P椭械娜魏蝺?nèi)容時(shí)需要?jiǎng)?chuàng)建,更新或刪除文檔的原因苫昌。最好的方法是添加一個(gè)Django信號(hào)調(diào)度程序颤绕。在添加信號(hào)之前,讓我們創(chuàng)建一個(gè)序列化器來(lái)創(chuàng)建祟身,更新和刪除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')
在我們需要?jiǎng)?chuàng)建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)
簡(jiǎn)單的django REST框架搜索視圖
最后,讓我們創(chuàng)建一個(gè)簡(jiǎn)單的搜索視圖袜硫,查找按標(biāo)簽過(guò)濾的所有帖子氯葬,并按標(biāo)題中的單詞進(jìn)行搜索:
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',
)
就是這樣,我們可以開(kāi)始使用它了婉陷。
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
分頁(yè)
分頁(yè)響應(yīng)的示例
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',
)