django使用haystack調(diào)用Elasticsearch實(shí)現(xiàn)索引搜索
前言:
在做一個(gè)商城項(xiàng)目的時(shí)候,需要實(shí)現(xiàn)商品搜索功能。
說到搜索,第一時(shí)間想到的是數(shù)據(jù)庫的 select * from tb_sku where name like %蘋果手機(jī)%
或者django的 SKU.objects.filter(name__contains="蘋果手機(jī)")
但是,假如你的數(shù)據(jù)庫有幾千萬條數(shù)據(jù),name字段沒有索引,可能查詢需要十幾分鐘,用戶可能會等你?那為什么不給name字段增加索引?商品表不僅僅是用來查詢,也會經(jīng)常修改數(shù)據(jù),新增刪除數(shù)據(jù)等。建立索引后,做增刪改操作時(shí)也會大大占用數(shù)據(jù)庫資源。所以應(yīng)該怎么解決呢?
Elasticsearch!
一個(gè)強(qiáng)大的基于Lucene的全文搜索服務(wù)器!維基百科、Stack Overflow、Github都在用。
如果想詳細(xì)了解其原理的話,可以參考:Elasticsearch 基礎(chǔ)介紹及索引原理分析
這里只是簡單說一下他的原理。
Elasticsearch原理:
部署好ElasticSearch服務(wù)器后,剛開始需要創(chuàng)建索引,ES索引庫會對數(shù)據(jù)庫中的數(shù)據(jù)進(jìn)行一遍預(yù)處理,單獨(dú)建立起一份索引結(jié)構(gòu)數(shù)據(jù)。
理解:
假如你的商品表里有這幾個(gè)字段。id,名字,副標(biāo)題,價(jià)格,商品圖片鏈接地址,評論數(shù),是否上架。
一般用戶會根據(jù)名字或者副標(biāo)題來搜索。此時(shí)名字、副標(biāo)題這個(gè)字段就需要建立索引(當(dāng)然,id也要,人家在mysql那里是主鍵總要給點(diǎn)面子吧)。但是后端返回給前端的數(shù)據(jù),不僅僅是需要名字、副標(biāo)題啊。你還要價(jià)格什么的呢!所以我們還要指定需要的字段,不然直接找個(gè)名字或者副標(biāo)題出來有什么用?
所以剛開始創(chuàng)建索引庫時(shí),ElasticSearch服務(wù)端會根據(jù)我們指定要作為索引的字段(名字、副標(biāo)題、id)、要返回的字段(價(jià)格...),同步一份到ES索引庫里面。為什么要同步到elasticsearch?因?yàn)椴檎铱煅?。至于為什么ElasticSearch查找這么快,可以參考一下上面鏈接的原理。
注意上面的圖,ElasticSearch是C/S架構(gòu)的軟件。下面說一下,服務(wù)端怎么搭建?
ElasticSearch服務(wù)端的搭建:
在搭建前說下,ElasticSearch建立索引時(shí)會分詞。什么是分詞呢?例如“我今天吃了一個(gè)漢堡包”。分詞后是“我”、“今天”、“吃了”、“一個(gè)”、“漢堡包”。你以為ElasticSearch會這么智能?沒錯(cuò),它對英文是這么智能,但是對我們的中文,只會分成“我”、“今”、“天”、“吃”、“了”、“一”、“個(gè)”、“漢”、“堡”、“包”。這樣用戶還怎么搜索啊。。。所以我們需要一個(gè)在ElasticSearch服務(wù)端集成一個(gè)插件,ElasticSearch-ik插件。有了這個(gè)插件,真的可以這么智能了。
所以,帶有-ik插件的ElasticSearch服務(wù)端怎么裝呢?
太麻煩了,所以我選擇docker(滑稽.jpg)
(1)加載docker鏡像
sudo docker load -i elasticsearch-ik-2.4.6_docker.tar
(2)修改配置文件
elasticsearc-2.4.6/config/elasticsearch.yml第54行,更改ip地址為本機(jī)ip地址:
network.host: xxx.xxx.xxx.xxx
如果docker不是運(yùn)行在開發(fā)環(huán)境的本機(jī),可以設(shè)為0.0.0.0。表示允許所有ip訪問此服務(wù)器。
(3)運(yùn)行容器
docker run -d -p 9200:9200 --network=host --name=elasticsearch -v /var/elasticsearch-2.4.6/config:/usr/share/elasticsearch/config delron/elasticsearch-ik:2.4.6-1.0
(4)測試ElasticSearch是否安裝成功
curl 'http://xxx.xxx.xxx.xxx:9200/' # IP地址是ElasticSearch的IP
如果測試成功,那么ElasticSearch服務(wù)器就已經(jīng)全部搭建完畢啦,而且這個(gè)鏡像集中了-ik插件,支持中文分詞。搭建完服務(wù)端后,就要用客戶端了。
使用Haystack對接Elasticsearch客戶端:
如果直接在Django項(xiàng)目直接編寫代碼作為ElasticSearch的客戶端,比較復(fù)雜,所以借助第三方包Haystack來對接ELasticSearch的客戶端。而且使用了Haystack后,以后你換其他的全文搜索服務(wù)器時(shí)(雖然不太可能換),也不用修改Django項(xiàng)目已經(jīng)寫好的代碼。
(1)安裝Haystack和ElasticSearch客戶端。
pip install drf-haystack # 因?yàn)樵擁?xiàng)目是用DRF寫的前后端分離,所以安裝的是drf-haystack。如果不用DRF的話,安裝的是django-haystack pip install elasticsearch==2.4.1
(2)配置
1.注冊應(yīng)用
INSTALLED_APPS = [ ... 'haystack', ... ]
2.在項(xiàng)目的配置文件中配置haystack
# 配置haystack全文檢索框架 HAYSTACK_CONNECTIONS = { 'default': { 'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine', # 此處為elasticsearch運(yùn)行的服務(wù)器ip地址,端口號默認(rèn)為9200 'URL': 'http://xxx.xxx.xxx.xxx:9200/', # 指定elasticsearch建立的索引庫的名稱 'INDEX_NAME': 'meiduo', }, } # 當(dāng)添加、修改、刪除數(shù)據(jù)時(shí),自動更新索引 HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
(3)創(chuàng)建索引類
創(chuàng)建索引類的目的是指定要保存的字段,ElasticSearch服務(wù)器會把mysql的這些字段的數(shù)據(jù)進(jìn)行同步。方便查詢出來時(shí)進(jìn)行返回。
# goods(應(yīng)用名)/search_indexes.py # search_indexes名字不能改,固定 from haystack import indexes from .models import SKU class SKUIndex(indexes.SearchIndex, indexes.Indexable): """ SKU索引類 """ # text表示被查詢的字段,用戶搜索的是這些字段的值,具體被索引的字段寫在另一個(gè)文件里。 text = indexes.CharField(document=True, use_template=True) # 保存在索引庫中的字段 id = indexes.IntegerField(model_attr='id') name = indexes.CharField(model_attr='name') price = indexes.DecimalField(model_attr='price') default_image_url = indexes.CharField(model_attr='default_image_url') comments = indexes.IntegerField(model_attr='comments') def get_model(self): """返回建立索引的模型類""" return SKU def index_queryset(self, using=None): """返回要建立索引的數(shù)據(jù)查詢集""" return self.get_model().objects.filter(is_launched=True)
(4)指定被索引的字段
# templates/search/indexes/goods(應(yīng)用名)/sku_text.txt # 路徑和名字是固定的 {{ object.name }} {{ object.caption }} {{ object.id }}
(5)生成索引庫
python manage.py rebuild_index
此時(shí),索引庫成功生成了。接下來就是后端接受用戶存過來的查詢參數(shù),并返回相應(yīng)的字段了。
完善后端:
剛剛寫的SKUIndex可以當(dāng)做是我們平時(shí)寫DRF時(shí)的model類,接下來還要寫序列化器,視圖,注冊路由。
(1)Haystack序列化器類
from drf_haystack.serializers import HaystackSerializer class SKUIndexSerializer(HaystackSerializer): """ SKU索引結(jié)果數(shù)據(jù)序列化器 """ class Meta: index_classes = [SKUIndex] fields = ('text', 'id', 'name', 'price', 'default_image_url', 'comments')
(2)Haystack視圖
from drf_haystack.viewsets import HaystackViewSet class SKUSearchViewSet(HaystackViewSet): # HaystackViewSet繼承了RetrieveModelMixin, ListModelMixin, ViewSetMixin, HaystackGenericAPIView,所以可以查一條或多條數(shù)據(jù) """ SKU搜索 HaystackViewSet: 查一條,查多條 """ index_models = [SKU] serializer_class = SKUIndexSerializer
(3)注冊路由
router = DefaultRouter() router.register('skus/search', views.SKUSearchViewSet, base_name='skus_search') ... urlpatterns += router.urls
(4)訪問:127.0.0.1:8080/skus/search/?text=Apple
就可以查詢出帶有Apple的數(shù)據(jù)了~
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
對python中的float除法和整除法的實(shí)例詳解
今天小編就為大家分享一篇對python中的float除法和整除法的實(shí)例詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-07-07python創(chuàng)造虛擬環(huán)境方法總結(jié)
在本篇內(nèi)容里我們給大家整理了關(guān)于python創(chuàng)造虛擬環(huán)境的詳細(xì)方法和步驟,需要的朋友們學(xué)習(xí)下。2019-03-03python操作小程序云數(shù)據(jù)庫實(shí)現(xiàn)簡單的增刪改查功能
這篇文章主要介紹了python操作小程序云數(shù)據(jù)庫實(shí)現(xiàn)簡單的增刪改查功能,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-06-06用python + openpyxl處理excel2007文檔思路以及心得
最近要幫做RA的老姐寫個(gè)合并excel工作表的腳本……源數(shù)據(jù)是4000+個(gè)excel 工作表,分布在9個(gè)xlsm文件里,文件內(nèi)容是中英文混雜的一些數(shù)據(jù),需要從每張表中提取需要的部分,分門別類合并到多個(gè)大的表里。2014-07-07python讀取目錄下所有的jpg文件,并顯示第一張圖片的示例
今天小編就為大家分享一篇python讀取目錄下所有的jpg文件,并顯示第一張圖片的示例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-06-06Django框架登錄加上驗(yàn)證碼校驗(yàn)實(shí)現(xiàn)驗(yàn)證功能示例
這篇文章主要介紹了Django框架登錄加上驗(yàn)證碼校驗(yàn)實(shí)現(xiàn)驗(yàn)證功能,結(jié)合實(shí)例形式分析了Django框架基于Pillow模塊的圖形驗(yàn)證碼生成與使用相關(guān)操作技巧,需要的朋友可以參考下2019-05-05