ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是第二最流行的企业搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。本篇是在windows平台下的运用
由于elasticsearch是Java开发的,所以首先要安装Java环境
下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
下载好之后,直接安装, 切记:不要安装在C盘!, 注意环境变量的配置(JAVA_HOME)
不建议安装elasticsearch的官网版本,因为集成的插件比较少
下载地址:https://github.com/medcl/elasticsearch-rtf
该版本集成了一些会用到的插件。
解压后,在bin目录下打开命令行工具,输入elasticsearch.bat执行脚本,打开浏览器,在地址栏输入http://127.0.0.1:9200, 如果返回数据则表示运行成功
这是(搜索引擎)的可视化管理工具,安装要用到node.js的npm 插件管理器,所以要先安装node.js的npm 插件管理器。
下载地址:https://nodejs.org/en/download/
下载完成后,根据指引安装即可
(1)安装完后后,打开命令行工具
执行命令 npm
npm命令是node.js的npm插件管理器,也就是下载插件和安装插件的管理器,国外镜像很慢可能会掉线,我们使用淘宝的npm镜像cnpm
执行命令:npm install -g cnpm --registry=https://registry.npm.taobao.org
启用淘宝的npm镜像cnpm,注意:启用后当我们要输入npm命令时,就需要输入cnpm
(2)(搜索引擎)的可视化管理工具elasticsearch-head的安装
下载地址:https://github.com/mobz/elasticsearch-head
下载后解压到指定目录
(3)cd进入到解压的elasticsearch-head目录,安装elasticsearch-head的依赖包
执行命令:cnpm install
(4)启动elasticsearch-head(搜索引擎)的可视化管理工具,访问http://localhost:9100/,就可以看到(搜索引擎)的可视化管理工具。
执行命令:cnpm run start
点击连接会发现是灰色的未连接状态,这是因为elsaticsearch的安全策略,在5.0之后的版本不允许第三方插件直接连接,需要修改配置文件,在config文件夹下后缀为yml的文件中添加以下配置:
http.cors.enabled: true
http.cors.allow-origin: "*"
重启服务,点击连接,即可成功
elasticsearch的详细内容还请参阅相关文档,接下来会直接贴上我在使用elasticsearch来实现搜索引擎时的步骤和一些注意事项。搜索引擎是为了数据而存在的,所以你需要准备一个数据源,因此我用scrapy实现了一个简单的爬虫。
在使用前,为了准备数据要先启动爬虫将数据提交到elasticsearch,如感兴趣具体可前往https://github.com/xinyan818/SimpleSearch-TST
doc_type在elasticsearch中类似关系型数据库中的数据表,我们需要实现它。
# 数据类型
from elasticsearch_dsl import DocType, Completion, Keyword, Text, Boolean, Integer, Date
# 引入链接函数
from elasticsearch_dsl.connections import connections
# 引入elasticsearch中的分析器
from elasticsearch_dsl.analysis import CustomAnalyzer
# 创建Es链接
connections.create_connection(hosts=["127.0.0.1"])
# 自定义分词器
class MyAnalyzer(CustomAnalyzer):
def get_analysis_definition(self):
return {}
# 创建分析器对象
# 忽略大小写的筛选器
ik_analyzer = MyAnalyzer('ik_max_word', filter=['lowercase'])
class NewsType(DocType):
# 搜索建议字段
# Completion 用来做搜索建议的类型
# 不能直接指定分词器名,需要指定一个自定义分词器
suggest = Completion(analyzer=ik_analyzer)
# 分词
title = Text(analyzer="ik_max_word")
category = Text()
f_url = Text()
intro = Text(analyzer="ik_max_word")
source = Text()
time = Date()
# Meta
class Meta:
# 索引名称
index = 'news'
doc_type = 'fashion'
if __name__ == '__main__':
NewsType.init()
运行这个python文件即可在服务中声明一个名为news的index,和在其之下名为fashion的type,
#搜索结果页面
def result(request):
if request.method == 'GET':
# 取出关键词 搜索类型 页码
keyword = request.GET.get('kw', None)
s_type = request.GET.get('s_type', 'blog')
page_num = request.GET.get('pn', 1)
# 没有关键词,定向到首页
if not keyword:
return redirect('/')
# 判断搜索类型
# 搜索
if s_type == 'news':
# 1. 搜索的索引
index = 'news'
doc_type = 'fashion'
fields = ['title', 'intro']
start = datetime.now()
rs = es.search(
index=index,
doc_type=doc_type,
body={
'query': {
'multi_match': {
'query': keyword,
'fields': fields
}
},
'from': (int(page_num)-1)*10,
'size': 10,
'highlight': {
'pre_tags': [''],
'post_tags': [''],
'fields': {
'title': {},
'intro': {}
}
}
}
)
# 搜索花费时间
# total_seconds() 统计秒数
use_time = (datetime.now() - start).total_seconds()
hits_list = []
for hit in rs['hits']['hits']:
try:
h_dic = {}
# 判断highlight中有没有title
if 'title' in hit['highlight'].keys():
h_dic['title'] = hit['highlight']['title'][0]
else:
h_dic['title'] = hit['_source']['title']
# 再判断intro
if 'intro' in hit['highlight'].keys():
intro_list = hit['highlight']['intro']
intro_list.reverse()
h_dic['content'] = ''.join(intro_list)
else:
h_dic['content'] = hit['_source']['intro']
# 详情地址
h_dic['detail_url'] = hit['_source']['f_url']
except:
continue
hits_list.append(h_dic)
navs = NAVS
# 计算页码
total = rs['hits']['total']
page_nums = int(math.ceil(total/10))
page_num = int(page_num)
if page_num < 6:
if page_nums <= 10:
pages = range(1, page_nums+1)
else:
pages = range(1, 11)
elif (page_num >= 6) and (page_num <= page_nums - 5):
pages = range(page_num - 5, page_num + 5)
else:
if page_nums <= 10:
pages = range(1, page_nums+1)
else:
pages = range(page_nums-9, page_nums + 1)
data = {
'navs': navs,
'search_type': s_type,
'hits_list': hits_list,
'kw': keyword,
'pages': pages,
'page_nums': page_nums,
'pn': page_num,
'total': total,
'use_time': use_time
}
return render(request, 'result.html', data)