欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

分布式搜索引擎:Elasticsearch快速入门

时间:2023-07-17
文章目录

一、Elasticsearch介绍

1.1 介绍1.2 安装(Ubuntu 20.04)1.3 安装 Kinaba (官方客户端,可选)1.4 核心概念1.5 与 MySQL 对比 二、反向索引原理三、ES 安装插件

3.1 离线安装3.2 在线安装 四、ES 操作

4.1 索引操作4.2 映射操作

4.2.1 字段类型4.2.2 映射参数4.2.3 映射操作 4.3 文档操作4.4 文档查询

4.4.1 全文查询4.4.2 词语级别查询4.4.3 布尔查询4.4.5 过滤查询 4.5 排序4.6 分页4.7 高亮显示4.8 聚合(Aggregations) 五、IK 的使用六、通过 python 使用 Elasticsearch

本文中使用的 ES 为 7.x 版本。

一、Elasticsearch介绍 1.1 介绍

Elasticsearch(以下简称 ES)是一个开源的高扩展的分布式全文搜索引擎,它可以近乎实时的存储、查询数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。

ES 的底层是开源库 Apache Lucene,由于Lucene 库的原理十分复杂,还需要我们自己写代码实现接口,所以 ES 就使用 RESTful 风格的 API 封装了 Lucene,使其更加简单易用。

1.2 安装(Ubuntu 20.04)

导入 ES 的 PGP 密钥:

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -

上安装 apt-transport-https 包:

sudo apt-get install apt-transport-https

添加存储库:

echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-7.x.list

安装 ES:

sudo apt-get update && sudo apt-get install elasticsearch

启动服务:

sudo systemctl start elasticsearch.service

测试安装:

curl -X GET "localhost:9200/?pretty"

出现主机、版本等信息,就说明安装成功。

设置开机自启动(可选):

sudo systemctl enable elasticsearch.service

1.3 安装 Kinaba (官方客户端,可选)

到官网下载压缩包:传送门,这里以 windows 系统为例。

解压到合适的目录。

修改 config/kibana.yml 文件,找到 elasticsearch.hosts,去掉注释,改为 ES 的链接地址:

elasticsearch.hosts: ["http://localhost:9200"]

运行 bin/kibana.bat(windows下)。

用浏览器打开 http://localhost:5601。

主要是使用 dev tools,其他的看着玩玩。

1.4 核心概念

集群(Cluster):

ES 可以运行在许多互相合作的服务器上,以实现容错和高可用性,这些服务器的集合称为集群。

节点(Node):

集群中的每一个服务器称为一个节点。

分片(Shard):

所有数据存储的最小单元块。

副本(Replia):

副本是一个分片的精确复制,可以提高查询吞吐量或实现高可用性。每个分片可以有零个或多个副本。

全文查询(Full-text Search):

全文索引就是把内容根据词的意义进行分词,然后分别创建索引,例如”今日是周日我们出去玩” 可能会被分词成:“今天“,”周日“,“我们“,”出去玩“ 等token,这样当你搜索“周日” 或者 “出去玩” 都会把这句搜出来。

1.5 与 MySQL 对比

ES 本质上是一个分布式数据库,所以,其中的很多概念在关系型数据库中都能找到与之相类似的概念。

ESMySQLIndex 索引Database 数据库Type 类型(7.x 版本后被移除!)Table 表document 文档Row 记录或行Field 字段Column 字段或列Mapping 映射Schema 结构Everything is indexedIndex 索引Query DSLSQLGET http://……SELECT * FROM table ……PUT http://……UPDATe table SET ……

补充说明:

ES 会索引所有字段,经过处理后写入一个反向索引(Inverted Index,也叫倒排索引)。查找数据的时候,直接查找该索引。所以,Elastic 数据管理的顶层单位就叫做 Index(索引)。

同一个 Index 里面的 document,不要求有相同的结构(scheme),但是最好保持相同,这样有利于提高搜索效率。

类型可以看作是对同一索引下文档的分组(7.x 版本已经移除这一概念)。

在创建索引的时候,可以预先定义字段的数据类型及相关属性(静态映射),ES 也可以自己推断出数据类型(动态映射,不建议)。映射就是对字段数据类型的定义。

所有的操作都是通过 http 请求完成,而不是使用特定客户端的命令。

二、反向索引原理

反向索引(Inverted Index)也叫倒排索引,与之对应的是正向索引(Forward Index)。简单来说,正向索引是通过 key 找 value,反向索引则是通过 value 找 key。

我们以古诗的搜索为例,看看这两种索引建立方法各自的表现:

正向索引:一般以古诗在数据库中的 id 号作为索引,查询包含“明月”一词的古诗时,需要一个个读取古诗的内容,显然不适合我们的应用场景。反向索引在建立索引之前,将古诗的内容进行分词处理,比如“床前明月光”拆分为“床、前、明月、月光、光”。然后以这些词作为索引,以包含这些词的所有古诗为文档(MySQL 中叫记录)。这样,只要在索引中找到“明月”,就能一下子找到所有“明月”古诗。 三、ES 安装插件

ES 本身只支持英文分词,所以我们需要安装一个 Elasticsearch-Analysis-IK 插件(以下简称IK)来使其支持中文分词,我们就以此为例,学习一下 ES 的插件安装。

3.1 离线安装

从 github 下载 IK:传送门,注意版本要和 ES 的版本对应,IK 的 github 首页有对应表。

创建插件目录:

cd ES的根目录/plugins/ && mkdir ik

使用 apt 安装的 ES 根目录为 /usr/share/elasticsearch。

解压到 plugins/ik 目录。

3.2 在线安装

使用 elasticsearch-plugin 插件安装,在 ES 根目录下执行:

sudo ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.17.0/elasticsearch-analysis-ik-7.17.0.zip

注意!将“7.17.0”更换为你自己的 ES 版本。

安装完成后,重启 ES 使用即可。

四、ES 操作

下面的操作,均在 Kibana 的 Dev Tools 中完成。当然,也可以使用 curl 命令(如果会用 curl 的话),甚至 postman 等工具。

4.1 索引操作

新增索引:

PUT /索引名称{ "settings": { "index": { "number_of_shards": 分片数量, "number_of_replicas": 副本数量 } }}

注意!每个 Index (即数据库)的名字必须是小写。

settings 是可选的。

查询索引:

GET /索引名称

删除索引:

DELETE /索引名称

4.2 映射操作

ES 6.x 及以上版本中创建的索引只包含一个类型,不过旧版本创建的索引可以正常使用。而在 7.x 版本中类型被完全移除。

4.2.1 字段类型

字符串类型:text、keyword;数字类型:long、integer、short、byte、double、float;日期类型:date;布尔类型:boolean;二进制类型:binary;复杂类型:object(对象或实体)、nested(列表);geo 类型:geo-point、geo-shape(地理位置);专业类型:ip、competion(搜索建议)。 4.2.2 映射参数 属性描述适合类型store值为yes表示存储,no表示不存储,默认为noallindexyes表示分析,no表示不分析,默认为truetextnull_value如果字段为空,可以设置一个默认值,比如"NA"(传过来为空,不能搜索,na可以搜索)allanalyzer可以设置索引和搜索时用的分析器,默认使用的是standard分析器,还可以使用whitespace,simple。都是英文分析器allinclude_in_all默认es为每个文档定义一个特殊域_all,它的作用是让每个字段都被搜索到,如果想让某个字段不被搜索到,可以设置为falseallformat时间格式字符串模式date4.2.3 映射操作

创建索引的同时创建映射:

PUT 索引名称{ "mapping":{ "字段名称":类型, "age": { "type": "integer" }, "email": { "type": "keyword" }, "name": { "type": "text" } }}

向已存在映射添加字段:

PUT 索引名称/_mapping{ "properties": { "字段名称":类型, }}

更新映射:

不允许更新,只能新建索引,然后将重新索引数据。

查询映射:

GET 索引名称/_mapping

删除映射:

只能连通索引一起删除。

4.3 文档操作

索引文档(即插入文档或者说给文档建立索引):

POST 索引名称/_doc{ "@timestamp": "2099-05-06T16:21:15.000Z", "event": { "original": "192.0.2.42 - - [06/May/2099:16:21:15 +0000] "GET /images/bg.jpg HTTP/1.0" 200 24736" }}

_doc 就是7.x 及更高版本默认的类型(type),不允许再创建。

插入文档时,可以不按照映射来,多几个或少几个字段都能正常插入。

如果向不存在的索引插入文档,会自动创建索引。

查询文档:

GET 索引名称/_doc/id号

修改文档:

POST 索引名称/_update/id号{ "doc": { "name": "new_name" }}

删除文档:

DELETE 索引名称/_doc/id号

4.4 文档查询 4.4.1 全文查询

全文查询会将用户给出的关键字进行分词处理,然后用分好的词进行查询。

match:

分词后任意一个词项匹配,文档就会查询到。

GET 索引名称/_doc/_search{ "query":{ "match":{ "字段":"值" "name":"hugh" } }}

match_phrase:

文档满足以下条件才能被匹配:

分词后所有词项都要出现在该字段中。字段中所有的词项顺序要一致

GET 索引名称/_doc/_search{ "query":{ "match_phrase":{ "name":"hugh" } }}

match_phrase_prefix:

和match_phrase搜索类似,只不过支持词项的前缀匹配。

GET 索引名称/_search{ "query": { "match_phrase_prefix": { "name":"hu" } }}

multi_match搜索:

用于搜索多个字段。

GET 索引名称/_search{ "query": { "multi_match": { "query": "hugh", "fields": ["student", "Chinese"] } }}

上述语句会在student和Chinese字段中查询包含单词 hugh 的文档。

4.4.2 词语级别查询

与全文查询不同,词语级查询不会将关键字分词,而是精确匹配关键字。

term:

返回“地址”字段包含关键字“亚洲中国”的文档。

GET 索引名称/_search{ "query": { "term": { "地址":"亚洲中国" } }}

terms:

可以指定多个关键字,在文档中匹配到其中一个或全部,就返回该文档。

GET 索引名称/_search{ "query": { "terms": { "user.id": [ "kimchy", "elkbee" ], "boost": 1.0 } }}

4.4.3 布尔查询

通过下面四个操作符,将多个简单查询组合在一起:

must:必须匹配其中的条件,等价于 and。

should:可以匹配也可以不匹配,但是匹配到的文档,会增加评分(评分越高,排名越靠前)。

must_not:会剔除匹配到的文档。

filter:过滤子句,实现更加复杂的过滤。(下一小节单独学习)

GET 索引名称/_search{ "query": { "bool": { "must": [{ "term": { "text_entry": { "value": "must" } }} ], "should": [{ "term": { "text_entry": { "value": "have" } }} ] } }}

4.4.5 过滤查询

直接过滤:

给出字段和值,不符合的直接被过滤掉。

GET 索引名称/_search{ "query": { "bool": { "filter": { "term": { "字段": "值" } } } }}

范围过滤:

和 range 合用,过滤掉不在范围内的结果。range 选项:

gt : 大于。lt : 小于。gte : 大于等于。lte :小于等于。

GET 索引名称/_search{ "query": { "bool": { "must": { "term": { "merchant_id": "2501" } }, "filter": { "range": { "age": { "lte":25 } } } } }}

4.5 排序

GET 索引名称/_doc/_search{ "query":{ "match":{ "字段":"值" "name":"hugh" } }, "sort":[ { "排序字段":{ "order":"asc升序或者desc降序" } } ]}

4.6 分页

GET 索引名称/_doc/_search{ "query":{ "match":{ "字段":"值" "name":"hugh" } }, "from": 起始位置, "size": 每页文档数}

4.7 高亮显示

GET 索引名称/_doc/_search{ "query":{ "match":{ "字段":"值" "name":"hugh" } }, "highlight":[ { "pre_tags":"在搜索结果之前加的样式标签", "post_tags":"在结果后面加的样式标签", "fields":{ "要高亮的字段":{} } } ]}

4.8 聚合(Aggregations)

max:

GET 索引名称/_doc/_search{ "aggs": { "max_price": { "max": { "field": "price" } } }}

min:

GET 索引名称/_doc/_search{ "aggs": { "min_price": { "min": { "field": "price" } } }}

sum:

GET 索引名称/_doc/_search{ "query": { "constant_score": { "filter": { "match": { "type": "hat" } } } }, "aggs": { "hat_prices": { "sum": { "field": "price" } } }}

avg:

{ "aggs": { "avg_grade": { "avg": { "field": "grade" } } }}

五、IK 的使用

IK 的两种分词方式:

ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”,会穷尽各种可能的组合,适合 Term Query;

ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”,适合 Phrase 查询。

设置方法:

在建立索引时,通过 analyzer 指定:

PUT 索引名称{ "mappings":{ "properties":{ "字段名称":{ "type":"text", "analyzer":"分词方式" }, "字段名称":{ "type":"text", "analyzer":"分词方式" } } }}

六、通过 python 使用 Elasticsearch

Python Elasticsearch Client 是 ES 官方提供的底层客户端。

安装:

pip install elasticsearch

如果使用 async/await ,则使用下面的方法安装:

pip install elasticsearch[async]

快速入门:

# 导入客户端from elasticsearch import Elasticsearch# 实例化客户端实例es = Elasticsearch()# 插入文档doc = { 'author': 'kimchy', 'text': 'Elasticsearch: cool、bonsai cool.', 'timestamp': datetime.now(),}res = es.index(index="test-index", id=1, document=doc)# 查询文档res = es.search(index="test-index", body={"query": {"match_all": {}}})

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。