ElasticSearch基础知识
简介
ElasticSearch(以下简称ES)是一个基于Lucene的搜索服务器,它提供了一个分布式多用户能力的全文搜索引擎。基于RESTful web接口。要想深入了解 ES,需要先对 Lucene 有一个清晰的认识,那么什么是 Lucene 呢?
Lucene
普通数据库的缺陷:
- 没有高效的索引方式,查询的速度在大量数据的情况下很慢
- 搜索效果差,只能对用户输入的完整关键字进行首尾模糊匹配
- 用户搜索时如果错输,则查询的结果可能差别很大
搜索引擎
搜索引擎是指根据一定的策略,运用特定的计算机程序从互联网上搜集信息,对信息进行组织和处理后,为用户提供检索服务。将用户检索相关的信息展示给用户的系统。
分类:
垂直搜索:通常也叫做细分,指专门针对某一类信息进行搜索
综合搜索:是指对众多信息进行综合性的搜索,如:百度、谷歌。。。
站内搜索:对网站内部的信息进行搜索,对自己数据库进行搜索
软件内部搜索:如 word / idea 进行搜索
倒排索引技术
倒排索引(反向索引)以词条为索引,表中关键字对应的记录项记录了出现这个字或词的所有文档,每一个表项记录该文档的ID和关键字在该文档中出现的位置情况
全文检索
计算机对文档的全部内容进行分词,对每个词建立一个索引,索引记录单词出现的位置和c
Lucene 是一个开源的全文检索引擎工具包
安装
bin:脚本目录,包括:启动、停止等可执行脚本
config:配置文件目录
data:索引目录,存放索引文件的地方
logs:日志目录
modules:模块目录,包括了es的功能模块
plugins :插件目录,es支持插件机制
配置文件
三个配置文件
elasticsearch.yml:用于配置Elasticsearch运行参数
jvm.options:用于配置Elasticsearch JVM设置
log4j2.properties:用于配置Elasticsearch日志
es.yml
# 常用的配置项如下:
# 配置elasticsearch的集群名称,默认是elasticsearch。建议修改成一个有意义的名称。
cluster.name: YunShangXue
# 节点名称
node.name: masterNode
# 网络地址,配置成 0.0.0.0 代表任意地址
network.host: 0.0.0.0:
# HTTP端口号
http.port: 9200
# 集群交互的端口号
transport.tcp.port: 9300
# 指定该节点是否有资格被选举成为master结点,如果原来的master宕机会重新选举新的master
node.master: true
# 是否是数据节点
node.data: true
# 开发环境下集群节点的地址和端口们
discovery.zen.ping.unicast.hosts: ["0.0.0.0:9300", "0.0.0.0:9301", "0.0.0.0:9302"]
# 主结点数量的最少值 ,此值的公式为:(master_eligible_nodes / 2) + 1 ,比如:有3个符合要求的主结点,那么这里要设置为2。
discovery.zen.minimum_master_nodes: 1
# 锁住ES使用的内存,避免内存与swap分区交换数据。
bootstrap.memory_lock: false
# 单机允许的最大存储结点数,通常单机启动一个结点建议设置为1,开发环境如果单机启动多个节点可设置大于1
node.max_local_storage_nodes: 1
# 索引文件、日志文件路径
path.data: D:\ElasticSearch\elasticsearch‐6.2.1\data
path.logs: D:\ElasticSearch\elasticsearch‐6.2.1\logs
# 允许跨域?
http.cors.enabled: true
http.cors.allow‐origin: /.*/
# 设置ES自动发现节点连接超时的时间,默认为3秒,如果网络延迟高可设置大些。
discovery.zen.ping.timeout: 3s
jvm.options
设置最小及最大的JVM堆内存大小:
在jvm.options中设置 -Xms和-Xmx:
- 两个值设置为相等
- 将 Xmx 设置为不超过物理内存的一半。
log4j2.properties
日志文件设置,ES使用log4j,注意日志级别的配置。生产环境下设置为 error
安装 head 插件
- 下载
git clone git://github.com/mobz/elasticsearch-head.git cd elasticsearch-head npm install npm run start open
- 运行
Head操作ES
创建索引库
ES的索引库是一个逻辑概念,它包括了分词列表及文档列表,同一个索引库中存储了相同类型的文档。它就相当于
MySQL中的表,或相当于Mongodb中的集合
- 使用 RESTful 风格的方式来创建:使用 postman 发送如下请求
put http://localhost:9200/索引库名称(相当于创建了MySQL中的表)
{
"settings":{
"index":{
"number_of_shards":1, // 分片数量
"number_of_replicas":0 // 副本数量
}
}
}
- 使用 Head 插件直接创建
创建映射
概念说明
MySQL | ES |
---|---|
数据库 | |
表 | 索引库(6.0以后淡化了 Type 的概念,9.0将会取缔) |
字段 | 字段 |
行记录 | 文档 |
创建映射就是指定文档中包括的字段
PUT http://localhost:9200/索引库名称/类型名称/_mapping
这里我们使用的 ES 版本是 6.2.1 虽然已经弱化 Type 的概念,但是并没有完全删除,所以我们可以起一个没有任何意义的名称作为 Type
{
"properties": {
"name": {
"type": "text"
},
"description": {
"type": "text"
},
"studymodel": {
"type": "keyword"
}
}
}
如果想查询映射,将 put 请求切换成 get 请求即可
添加文档
请求格式:
POST http://localhost:9200/索引名/类型名/id值
如果不指定 id 值 ES 会自动生成 ID
{
"name":"Bootstrap开发框架",
"description":"Bootstrap是由Twitter推出的一个前台页面开发框架,在行业之中使用较为广泛。此开发框架包含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长页面开发的程序人员)轻松的实现一个不受浏览器限制的精美界面效果。",
"studymodel":"201001"
}
搜索文档
根据ID查询文档:
GET http://localhost:9200/ysx_course/doc/gf7ic2wBmvkgEzxNIJl0
查询全部文档
GET http://localhost:9200/ysx_course/doc/_search
根据 name 字段查询。查询的结果匹配度越高越靠前
GET http://localhost:9200/ysx_course/doc/_search?q=name:XXX
http://localhost:9200/ysx_course/doc/_search?q=name:Spring
查询到的结果
{
"took": 3, // 本次操作花费的时间/ms
"timed_out": false, // 请求是否超时
"_shards": {
"total": 1, // 查询到的结果数
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1, // 符合条件的文档总数
"max_score": 0.9530774, // 文档匹配得分,这里为最高分
"hits": [ // 匹配度较高的前N个文档
{
"_index": "ysx_course",
"_type": "doc",
"_id": "gf7ic2wBmvkgEzxNIJl0",
"_score": 0.9530774, // 每个文档都有一个匹配度得分,按照降序排列
"_source": { // 显示了文档的原始内容
"name": "Spring",
"description": "...",
"studymodel": "201001"
}
}
]
}
}
IK 分词器
因为 ES 是老外开发的,对中文的支持非常鸡肋,例如:发送请求测试原始分词效果
POST localhost:9200/_analyze
可以发现,ES 原始分词器将每个中文字都认为是一个词,这完全不符合我们的要求,因此我们需要安装中文分词器
下载IK
GITHUB 地址:https://github.com/medcl/elasticsearch-analysis-ik
安装
解压,并将解压的文件拷贝到ES安装目录的plugins下的ik目录下
重启ES测试
重新发送 HTTP 请求
POST localhost:9200/_analyze
在 JSON 数据中添加参数:
{"text":"中华人民共和国人民大会堂","analyzer":"ik_max_word"}
对于 analyzer 属性,是 ik 的分词模式。有两种取值:
- ik_max_word : 细粒度分词,如上面的文档会被分为: 中华人民共和国、中华、人民、共和国、华人…
- ik_smart : 粗粒度分词,中华人民共和国、人民大会堂。
自定义词库
对于一些我们网站自己用到的/非常见词条。我们就需要进行自定义词库了,怎么实现呢?
- 打开 ik 文件夹下 config 目录,IKAnalyzer.cfg.xml 文件。可以清楚的看出这个文件中可以配置自定义词库。这里我们在同级目录下创建 my.dic 文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">my.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
- 在 my.dic 文件中,每一行输入一个词条,并且保存成 无BOM UTF-8 格式文件。
- 重启 ES,进行测试
映射维护
说明
ES 支持映射的新增,但不支持已有字段的更新,如果非要进行更新,就需要删除索引库然后建立新的索引库。。。
常用映射类型
字符串: text
analyzer:属性指定分词器,下边指定name的字段类型为text,使用ik分词器的ik_max_word分词模式
"name": {
"type": "text",
"analyzer":"ik_max_word"
}
上边指定了analyzer是指在索引和搜索都使用ik_max_word,如果单独想定义搜索时使用的分词器则可以通过
search_analyzer属性.对于ik分词器建议是索引时使用 ik_max_word 将搜索内容进行细粒度分词,搜索时使用 ik_smart 提高搜索精确性。最终的 JSON 数据如下:
"name": {
"type": "text",
"analyzer":"ik_max_word",
"search_analyzer":"ik_smart"
}
index:该属性指定是否索引。默认是 true ,但是对于一些不用于搜索的字段,如图片 url ,就可以设置为 false
store:是否在source之外存储,每个文档索引后会在 ES中保存一份原始文档,存放在”_source”中,一般情况下不需要设置store为true,因为在_source中已经有一份原始文档了
字符串: keyword
keyword 定义的字段表示关键字搜索,是进行整体的搜索,在创建keyword时索引是不进行分词的,比如:邮编、身份证号、手机号等。keyword 字段通常用于过滤、排序、聚合等
日期: date
日期类型不用设置分词器。通常日期类型的字段用于排序。
format:通过format设置日期格式
{
"properties": {
"timestamp": {
"type": "date",
"format": "yyyy‐MM‐dd HH:mm:ss||yyyy‐MM‐dd" // 日期格式化
}
}
}
数值类型
ES 支持的数值类型有这么多:
在创建数值类型字段时,有以下几点建议:
- 尽量选择范围小的类型,以提高搜索效率
- 对于浮点数,尽量使用比例因子。例如金钱,设置比例因子为100,则 23.45 元会存储为 2345 分。如果输入的是 23.456 ES就会将它 * 100 然后四舍五入,存储成 2346 .使用比例因子的好处是整型比浮点型更易压缩,节省磁盘空间
"price": {
"type": "scaled_float",
"scaling_factor": 100
},
- 如果比例因子不适合,则从下表中选择合适的类型