Elasticsearch
開源的 Elasticsearch 是目前全文搜索引擎的首選撵幽。
它可以快速地儲(chǔ)存、搜索和分析海量數(shù)據(jù)。維基百科烘豌、Stack Overflow、Github 都采用它看彼。
Elasticsearch 的底層是開源庫(kù) Lucene廊佩。但是,你沒法直接用 Lucene靖榕,必須自己寫代碼去調(diào)用它的接口标锄。Elastic 是 Lucene 的封裝,提供了 REST API 的操作接口茁计,開箱即用料皇。
Elasticsearch 是用Java實(shí)現(xiàn)的。
搜索引擎在對(duì)數(shù)據(jù)構(gòu)建索引時(shí)星压,需要進(jìn)行分詞處理践剂。分詞是指將一句話拆解成多個(gè)單字或詞,這些字或詞便是這句話的關(guān)鍵詞租幕。如
我是中國(guó)人舷手。
'我'、'是'劲绪、'中'男窟、'國(guó)'、'人'贾富、'中國(guó)'等都可以是這句話的關(guān)鍵詞歉眷。
Elasticsearch 不支持對(duì)中文進(jìn)行分詞建立索引,需要配合擴(kuò)展elasticsearch-analysis-ik來實(shí)現(xiàn)中文分詞處理颤枪。
4. 使用Docker安裝Elasticsearch及其擴(kuò)展
獲取鏡像汗捡,可以通過網(wǎng)絡(luò)pull
docker image pull delron/elasticsearch-ik:2.4.6-1.0
或者加載提供給大家的鏡像文件
docker load -i elasticsearch-ik-2.4.6_docker.tar
修改elasticsearch的配置文件 elasticsearc-2.4.6/config/elasticsearch.yml第54行,更改ip地址為本機(jī)ip地址
network.host: 10.211.55.5
創(chuàng)建docker容器運(yùn)行
docker run -dti --network=host --name=elasticsearch -v /home/python/elasticsearch-2.4.6/config:/usr/share/elasticsearch/config delron/elasticsearch-ik:2.4.6-1.0
5. 使用haystack對(duì)接Elasticsearch
Haystack為Django提供了模塊化的搜索畏纲。它的特點(diǎn)是統(tǒng)一的扇住,熟悉的API,可以讓你在不修改代碼的情況下使用不同的搜索后端(比如 Solr, Elasticsearch, Whoosh, Xapian 等等)盗胀。
我們?cè)赿jango中可以通過使用haystack來調(diào)用Elasticsearch搜索引擎艘蹋。
1)安裝
pip install drf-haystack
pip install elasticsearch==2.4.1
drf-haystack是為了在REST framework中使用haystack而進(jìn)行的封裝(如果在Django中使用haystack,則安裝django-haystack即可)票灰。
2)注冊(cè)應(yīng)用
INSTALLED_APPS = [
...
'haystack',
...
]
3)配置
在配置文件中配置haystack使用的搜索引擎后端
# Haystack
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
'URL': 'http://10.211.55.5:9200/', # 此處為elasticsearch運(yùn)行的服務(wù)器ip地址女阀,端口號(hào)固定為9200
'INDEX_NAME': 'meiduo', # 指定elasticsearch建立的索引庫(kù)的名稱
},
}
# 當(dāng)添加宅荤、修改、刪除數(shù)據(jù)時(shí)浸策,自動(dòng)生成索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
注意:
HAYSTACK_SIGNAL_PROCESSOR 的配置保證了在Django運(yùn)行起來后冯键,有新的數(shù)據(jù)產(chǎn)生時(shí),haystack仍然可以讓Elasticsearch實(shí)時(shí)生成新數(shù)據(jù)的索引
4)創(chuàng)建索引類
通過創(chuàng)建索引類庸汗,來指明讓搜索引擎對(duì)哪些字段建立索引惫确,也就是可以通過哪些字段的關(guān)鍵字來檢索數(shù)據(jù)。
在goods應(yīng)用中新建search_indexes.py文件蚯舱,用于存放索引類
from haystack import indexes
from .models import SKU
class SKUIndex(indexes.SearchIndex, indexes.Indexable):
"""
SKU索引數(shù)據(jù)模型類
"""
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)
在SKUIndex建立的字段雕薪,都可以借助haystack由elasticsearch搜索引擎查詢。
其中text字段我們聲明為document=True晓淀,表名該字段是主要進(jìn)行關(guān)鍵字查詢的字段, 該字段的索引值可以由多個(gè)數(shù)據(jù)庫(kù)模型類字段組成盏档,具體由哪些模型類字段組成凶掰,我們用use_template=True表示后續(xù)通過模板來指明。其他字段都是通過model_attr選項(xiàng)指明引用數(shù)據(jù)庫(kù)模型類的特定字段蜈亩。
在REST framework中懦窘,索引類的字段會(huì)作為查詢結(jié)果返回?cái)?shù)據(jù)的來源。
6)在templates目錄中創(chuàng)建text字段使用的模板文件
具體在templates/search/indexes/goods/sku_text.txt文件中定義
{{ object.name }}
{{ object.caption }}
{{ object.id }}
此模板指明當(dāng)將關(guān)鍵詞通過text參數(shù)名傳遞時(shí)稚配,可以通過sku的name畅涂、caption、id來進(jìn)行關(guān)鍵字索引查詢道川。
7)手動(dòng)生成初始索引
python manage.py rebuild_index
8)創(chuàng)建序列化器
在goods/serializers.py中創(chuàng)建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')
注意fields屬性的字段名與SKUIndex類的字段對(duì)應(yīng)午衰。
9)創(chuàng)建視圖
在goods/views.py中創(chuàng)建視圖
from drf_haystack.viewsets import HaystackViewSet
class SKUSearchViewSet(HaystackViewSet):
"""
SKU搜索
"""
index_models = [SKU]
serializer_class = SKUIndexSerializer
注意:
- 該視圖會(huì)返回搜索結(jié)果的列表數(shù)據(jù),所以如果可以為視圖增加REST framework的分頁(yè)功能冒萄。
- 我們?cè)趯?shí)現(xiàn)商品列表頁(yè)面時(shí)已經(jīng)定義了全局的分頁(yè)配置臊岸,所以此搜索視圖會(huì)使用全局的分頁(yè)配置。
返回的數(shù)據(jù)舉例如下:
{
"count": 10,
"next": "http://api.meiduo.site:8000/skus/search/?page=2&text=%E5%8D%8E",
"previous": null,
"results": [
{
"text": "華為 HUAWEI P10 Plus 6GB+64GB 鉆雕金 移動(dòng)聯(lián)通電信4G手機(jī) 雙卡雙待\nwifi雙天線設(shè)計(jì)尊流!徠卡人像攝影帅戒!P10徠卡雙攝拍照,低至2988元崖技!\n9",
"id": 9,
"name": "華為 HUAWEI P10 Plus 6GB+64GB 鉆雕金 移動(dòng)聯(lián)通電信4G手機(jī) 雙卡雙待",
"price": "3388.00",
"default_image_url": "http://10.211.55.5:8888/group1/M00/00/02/CtM3BVrRcUeAHp9pAARfIK95am88523545",
"comments": 0
},
{
"text": "華為 HUAWEI P10 Plus 6GB+128GB 鉆雕金 移動(dòng)聯(lián)通電信4G手機(jī) 雙卡雙待\nwifi雙天線設(shè)計(jì)逻住!徠卡人像攝影!P10徠卡雙攝拍照迎献,低至2988元瞎访!\n10",
"id": 10,
"name": "華為 HUAWEI P10 Plus 6GB+128GB 鉆雕金 移動(dòng)聯(lián)通電信4G手機(jī) 雙卡雙待",
"price": "3788.00",
"default_image_url": "http://10.211.55.5:8888/group1/M00/00/02/CtM3BVrRchWAMc8rAARfIK95am88158618",
"comments": 5
}
]
}
10)定義路由
通過REST framework的router來定義路由
router = DefaultRouter()
router.register('skus/search', views.SKUSearchViewSet, base_name='skus_search')
...
urlpatterns += router.urls
11)測(cè)試
我們可以GET方法訪問如下鏈接進(jìn)行測(cè)試
http://api.meiduo.site:8000/skus/search/?text=wifi
http://api.meiduo.site:8000/skus/search/?id=1
http://api.meiduo.site:8000/skus/search/?name=iphone