Flask Vue.js全栈开发|第18章:Elasticsearch全文搜索

  • 原创
  • Madman
  • /
  • /
  • 6
  • 16761 次阅读

flask vuejs 全栈开发-min.png

Synopsis: 博客文章数量一旦比较多的时候,用关键字进行全文检索就很有必要了,目前开源的全文搜索引擎有 Elasticsearch、Apache Solr、Whoosh 等,本文选择 Elasticsearch 7.0 来实现博客文章内容的全文搜索,并对搜索关键词进行高亮

本系列的最新代码将持续更新到: http://www.madmalls.com/blog/post/latest-code/

0 Elasticsearch全文搜索与高亮

1. 安装 Elasticsearch 7

参考: https://www.elastic.co/guide/en/elasticsearch/reference/current/rpm.html

1.1 安装 JAVA 8

Elasticsearch 是使用 Java 编写的,它的内部使用 Lucene 做索引与搜索,但是它的目的是使 全文检索 变得简单,通过隐藏 Lucene 的复杂性,取而代之的提供一套简单一致的 RESTful API。所以,Elasticsearch 需要 java8 或更高版本,先检查 CentOS 7 的 JAVA 版本:

[root@CentOS ~]# java -version

如果还没有安装,或版本过低,请先安装 JAVA:

[root@CentOS ~]# yum -y install java-1.8.0-openjdk

1.2 安装 Elasticsearch RPM

# 1. Download and install the public signing key
[root@CentOS ~]# rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch

# 2. Create yum repository
[root@CentOS ~]# vim /etc/yum.repos.d/elasticsearch.repo
内容如下:

[elasticsearch-7.x]
name=Elasticsearch repository for 7.x packages
baseurl=https://artifacts.elastic.co/packages/7.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md

# 3. Install Elasticsearch
[root@CentOS ~]# yum -y install elasticsearch
[root@CentOS ~]# systemctl start elasticsearch.service
[root@CentOS ~]# systemctl enable elasticsearch.service

Elasticsearch 安装好后,默认的安装目录为 /usr/share/elasticsearch,默认的配置文件目录为 /etc/elasticsearch,默认的启动端口为 9200

测试 Elasticsearch 是否启动成功:

[root@CentOS ~]# curl 'http://localhost:9200/?pretty'
{
  "name" : "CentOS",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "VCi-CCWYRjaInhykJS4asg",
  "version" : {
    "number" : "7.0.0",
    "build_flavor" : "default",
    "build_type" : "rpm",
    "build_hash" : "b7e28a7",
    "build_date" : "2019-04-05T22:55:32.697037Z",
    "build_snapshot" : false,
    "lucene_version" : "8.0.0",
    "minimum_wire_compatibility_version" : "6.7.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

你也可以继续在 /etc/elasticsearch/elasticsearch.yml 配置文件中修改 cluster.namenode.namepath.datanetwork.hosthttp.port 等参数,比如你想让其它主机访问此服务器(IP:192.168.40.121)上的 Elasticsearch 服务的话,需要修改 network.hostdiscovery.seed_hosts

network.host: localhost, 192.168.40.121
discovery.seed_hosts: ["localhost", "192.168.40.121"]

ES 6 跟 ES 7 修改的参数不一样,出问题了记得查看 Elasticsearch 的日志 /var/log/elasticsearch/elasticsearch.log

Elasticsearch API 基本使用请参考: http://www.madmalls.com/blog/post/elasticsearch-basic/

2. 安装中文分词 ik

由于博文基本上是中文字符,使用 Elasticsearch 默认的词法分析器效果不好,所以需要安装 elasticsearch-analysis-ik

首先确认你的 Elasticsearch 版本号是多少,我们刚安装的是 Elasticsearch-7.0.0,所以到 https://github.com/medcl/elasticsearch-analysis-ik/releases 这个页面下载对应的 ik 版本(elasticsearch-analysis-ik-7.0.0.zip

[root@CentOS ~]# /usr/share/elasticsearch/bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.0.0/elasticsearch-analysis-ik-7.0.0.zip

[root@CentOS ~]# ls /usr/share/elasticsearch/plugins
analysis-ik
[root@CentOS ~]# /usr/share/elasticsearch/bin/elasticsearch-plugin list
analysis-ik

需要重启 Elasticsearch 服务!

3. Python Elasticsearch Client

参考: https://elasticsearch-py.readthedocs.io/en/master/

3.1 安装客户端

通过 pip 安装 Python 版本的 Elasticsearch 客户端 elasticsearch 包:

(venv)$ pip install elasticsearch
(venv)$ pip freeze > requirements.txt

3.2 测试

打开 ipython,如果你没安装请执行 pip install ipython

In [1]: from elasticsearch import Elasticsearch

In [2]: es = Elasticsearch('http://192.168.40.121:9200')

In [3]: es.indices.create(index='posts', ignore=400)  # 1. 创建名为 posts 的Index
Out[3]: {'acknowledged': True, 'shards_acknowledged': True, 'index': 'posts'}

In [4]: mapping = {
   ...:     'properties': {
   ...:         'content': {
   ...:             'type': 'text',
   ...:             'analyzer': 'ik_max_word',
   ...:             'search_analyzer': 'ik_max_word'
   ...:         }
   ...:     }
   ...: }

In [5]: es.indices.put_mapping(index='posts', body=mapping)  # 2. 设置Mapping,每个文档有个 content 字段,它的类型是 text,词法分析器是 ik
Out[5]: {'acknowledged': True}

In [6]: es.index(index='posts', id=1, body={'content': '美国留给伊拉克的是个烂摊子吗'})  # 3. 插入文档,每个文档必须使用唯一的 id
Out[6]:
{'_index': 'posts',
 '_type': '_doc',
 '_id': '1',
 '_version': 1,
 'result': 'created',
 '_shards': {'total': 2, 'successful': 1, 'failed': 0},
 '_seq_no': 0,
 '_primary_term': 1}

In [7]: es.index(index='posts', id=2, body={'content': '公安部:各地校车将享最高路权'})
Out[7]:
{'_index': 'posts',
 '_type': '_doc',
 '_id': '2',
 '_version': 1,
 'result': 'created',
 '_shards': {'total': 2, 'successful': 1, 'failed': 0},
 '_seq_no': 1,
 '_primary_term': 1}

In [8]: es.index(index='posts', id=3, body={'content': '中韩渔警冲突调查:韩警平均每天扣1艘中国渔船'})
Out[8]:
{'_index': 'posts',
 '_type': '_doc',
 '_id': '3',
 '_version': 1,
 'result': 'created',
 '_shards': {'total': 2, 'successful': 1, 'failed': 0},
 '_seq_no': 2,
 '_primary_term': 1}

In [9]: es.index(index='posts', id=4, body={'content': '中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首'})
Out[9]:
{'_index': 'posts',
 '_type': '_doc',
 '_id': '4',
 '_version': 1,
 'result': 'created',
 '_shards': {'total': 2, 'successful': 1, 'failed': 0},
 '_seq_no': 3,
 '_primary_term': 1}

In [10]: es.search(index='posts', body={'query': {'match': {'content': '中国'}}})  # 4. 搜索 '中国'
Out[10]:
{'took': 188,
 'timed_out': False,
 '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0},
 'hits': {'total': {'value': 2, 'relation': 'eq'},
  'max_score': 0.6548752,
  'hits': [{'_index': 'posts',
    '_type': '_doc',
    '_id': '3',
    '_score': 0.6548752
                                
                            
  • codeblind
  • sunny
  • nihao
  • Dawn Inator
  • zhuyulin
  • ygren
  • wulvtutu
  • Lunaticsky-tql
  • nickzxhfjsm
  • 雀AI2023
  • anthony
  • Team12
  • ReinXD
  • sdwfqhy
  • 邱晨100
  • JT Z
  • theuhy
  • jingyiweishang
  • Jinfan Liu
  • luohuai1Q84
  • binrr
  • zscsd
  • mingyun
  • 415670177
未经允许不得转载: LIFE & SHARE - 王颜公子 » Flask Vue.js全栈开发|第18章:Elasticsearch全文搜索

分享

作者

作者头像

Madman

如需 Linux / Python 相关问题付费解答,请按如下方式联系我

6 条评论

shishijia
shishijia

博主你好,我没怎么接触过代码部署,这方面不太懂。我看Elasticsearch 7、中文分词ik都是在centos下安装的,那之后的通过 pip 安装 Python 版本的 Elasticsearch客户端elasticsearch 包、ipython,还有全文搜索代码的添加也是在centos下操作吗,还是在本地的windows下操作修改好后再上传到centos上?如果可以在本地windows操作,是不是也不能运行,只有部署到centos才能运行?

Madman
Madman shishijia Author

elasticsearch服务端和ik中文分词插件安装在CentOS服务器上,它会监听9200端口提供存储和查询数据的服务,就像MySQL数据库会监听3306端口一样。而你的Python代码中通过elasticsearch或pymysql这种Python版本的客户端来连接这些服务即可(IP加端口),所以Python代码可以跟这些服务运行在同一台计算机上,也可以分开运行

shishijia
shishijia

谢谢博主。不好意思,我还想问如果我不想在本地windows下安装elasticsearch,只在centos下安装elasticsearch。我还能在windows的环境下运行这一功能吗?这属于远程开发吗?

shishijia
shishijia

博主,我在curl 'http://localhost:9200/?pretty'时一直报错curl: (7) Failed connect to localhost:9200; 拒绝连接。 我感觉是端口问题,可我已经在/etc/sysconfig/iptables里添加了 -A INPUT -m state --state NEW -m tcp -p tcp --dport 9200 -j ACCEPT,在本地windows浏览器测试192.168.221.128:9200/?pretty,显示192.168.221.129 拒绝了我们的连接请求。 请问

M4nkeys
M4nkeys

您好,麻烦问一下搜出结果后,点击某一个结果,然后跳转到相应的位置是怎么实现的?

Madman
Madman M4nkeys Author

front-end/src/SearchResult.vue 中第 117 行生成博文详情页的链接:

<router-link v-bind:to="{ name: 'PostDetail', params: { id: post.id }, query: { q: $route.query.q, page: $route.query.page, per_page: $route.query.per_page } }" class="btn btn-xs u-btn-outline-primary">阅读全文</router-link>

专题系列