一. ES快速入门
ES作为一个索引及搜索服务,对外提供丰富的REST接口,快速入门部分的实例使用kibana来测试,目的是对ES的使用方法及流程有个初步的认识。
1.1 idex管理
1.1.1 创建index库
索引库。包含若干相似结构的 Document 数据,相当于数据库的database。
语法:put /index_name
- 如:
PUT /java06
{
"settings": {
"number_of_shards": 2,
"number_of_replicas": 1
}
}
- number_of_shards - 表示一个索引库将拆分成多片分别存储不同的结点,提高了ES的处理能力
- number_of_replicas - 是为每个 primary shard分配的replica shard数,提高了ES的可用性,如果只有一台机器,设置为0
- 效果(当前是head客户端展示的):
1.1.2 修改index
注意:索引一旦创建,primary shard 数量不可变化,可以改变replica shard 数量。
语法:put /index_name/_settings
- 如:
PUT /java06/_settings
{
"number_of_replicas" : 5
}
1.1.3 删除index
语法: DELETE /index_name[, other_index]
1.2 mapping管理
映射,创建映射就是向索引库中创建field(类型、是否索引、是否存储等特性)的过程,下边是document和field与关系数据库的概念的类比:
elasticsearch | 关系数据库 |
---|---|
index(索引库) | database(数据库) |
type(类型) | table(表) |
document(文档) | row(记录) |
field(域) | column(字段) |
注意:6.0之前的版本有type(类型)概念,type相当于关系数据库的表,ES6.x 版本之后,type概念被弱化ES官方将在ES7.0版本中彻底删除type
1.2.1 创建mapping
语法: POST /index_name/type_name/_mapping
- 如:
POST /java06/class/_mapping
{
"properties": {
"name": {
"type": "text"
},
"sex": {
"type": "text"
},
"age": {
"type": "interge"
}
}
}
1.2.2 查询mapping
查询所有索引的映射:
语法: GET /index_name/type_name/_mapping
1.2.3 修改mapping
- 映射创建成功可以添加新字段,已有字段不允许更新。
1.2.4 删除mapping
- 通过删除索引来删除映射。
1.3 document管理
1.3.1 创建document
ES中的文档相当于MySQL数据库表中的记录。
1.3.1.1 POST语法
语法: POST /index_name/type_name/id
-
如
POST /java06/class/1
{
"name":"张红",
"sex":"女",
"age":"19"
}POST /java06/class
{
"name":"张三",
"sex":"男",
"age":18
}
1.3.1.2 PUT语法
此操作为手工指定 id 的 Document 新增方式。当前没有此条记录的时候相当于新建
语法:PUT/index_name/type_name/id{field_name:field_value}
- 如:
PUT /java06/course/1
{
"name":"张红1",
"sex":"女",
"age":"22"
}
- 结果:
{
"_index": "test_index", 新增的 document 在什么 index 中,
"_type": "my_type", 新增的 document 在 index 中的哪一个 type 中。
"_id": "1", 指定的 id 是多少
"_version": 1, document 的版本是多少,版本从 1 开始递增,每次写操作都会+1
"result": "created", 本次操作的结果,created 创建,updated 修改,deleted 删除
"_shards": { 分片信息
"total": 2, 分片数量只提示 primary shard
"successful": 1, 数据 document 一定只存放在 index 中的某一个 primary shard 中
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}
1.3.2 查询document
语法: GET /index_name/type_name/id
或: GET /index_name/type_name/_search?q=field_name:field_value
根据课程id查询文档:
GET /java06/class/1
查询所有记录:
GET /java06/class/_search
查询名称中包括php 关键字的的记录:
GET /java06/course/_search?q=name:张
1.3.3 删除 document
ES 中执行删除操作时,ES先标记Document为deleted状态,而不是直接物理删除。当ES 存储空间不足或工作空闲时,才会执行物理删除操作,标记为deleted状态的数据不会被查询搜索到(ES 中删除 index ,也是标记。后续才会执行物理删除。所有的标记动作都是为了NRT(近实时)实现)
语法: DELETE /index_name/type_name/id
- 如:
DELETE /java06/class/1
1.4 ES读写过程
1.4.1 documnet routing(数据路由)
当客户端创建document的时候,es需要确定这个document放在该index哪个shard上,这个过程就是document routing。
- 路由过程:
路由算法:shard = hash(5) %number_of_primary_shards
id:document的_id,可能是手动指定,也可能是自动生成,决定一个document在哪个shard上
number_of_primary_shards:主分片數量。
1.4.2 为什么primary shard数量不可变?
假如我们的集群在初始化的时候有5个primary shard,我们往里边加入一个document id=5,假如hash(5)=23,这时该document 将被加入 (shard=23%5=3)P3这个分片上。如果随后我们给es集群添加一个primary shard ,此时就有6个primary shard,当我们GET id=5 ,这条数据的时候,es会计算该请求的路由信息找到存储他的 primary shard(shard=23%6=5) ,根据计算结果定位到P5分片上。而我们的数据在P3上。所以es集群无法添加primary shard,但是可以扩展replicas shard。
二. luke查看ES的逻辑结构
2.1 luke是什么?
- Luke是一个用于Lucene搜索引擎的,方便开发和诊断的第三方工具,它可以访问现有Lucene的索引,并允许您显示和修改。
- Luke是一个方便宜的开发和诊断工具,它能访问Lucene建立好的索引同时也允许以如下的一些方式展示和修改内容:
2.2 安装
官方下载地址https://github.com/DmitryKey/luke/releases下载对应版本即可
2.3 解压运行 luke.bat
- 5.0.0以上版本(点击luke.bat 即可启动Luke)
2.4 测试
2.5 luke查看ES的逻辑结构
拷贝elasticsearch-6.2.3(es路径下的)/data到windows
双击luke.bat,启动luke
使用luke打开data\nodes\0\indices路径
三. IK分词器
3.1 测试分词器
在添加文档时会进行分词,索引中存放的就是一个一个的词(term),当你去搜索时就是拿关键字去匹配词,最终找到词关联的文档。
测试当前索引库使用的分词器:
POST /_analyze
{
"text":"测试分词器,后边是测试内容:spring cloud实战"
}
- 结果如下:
会发现分词的效果将“测试”这个词拆分成两个单字“测”和“试”,这是因为当前索引库使用的分词器对中文就是单字分词。
3.2 中文分词器
3.2.1 Lucene自带中文分词器
- StandardAnalyzer:单字分词:就是按照中文一个字一个字地进行分词
- CJKAnalyzer:二分法分词:按两个字进行切分
- SmartChineseAnalyzer:对中文支持较好,但扩展性差,扩展词库和禁用词库等不好处理
3.2.2 第三方中文分析器
- IK-analyzer:
最新版在https://code.google.com/p/ik-analyzer/上,支持Lucene 4.10从2006年12月推出1.0版开始, IKAnalyzer已经推出了4个大版本。最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。从3.0版本开 始,IK发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。在2012版本中,IK实现了简单的分词 歧义排除算法,标志着IK分词器从单纯的词典分词向模拟语义分词衍化。 但是也就是2012年12月后没有在更新。
3.3 安装IK分词器
使用IK分词器可以实现对中文分词的效果
下载链接https://github.com/medcl/elasticsearch-analysis-ik
3.3.1 下载zip:
3.3.2 解压安装
将解压的文件拷贝到ES安装目录的plugins下的ik(重命名)目录下,重启es
3.3.3 测试分词效果:
POST /_analyze
{
"text":"中华人民共和国人民大会堂",
"analyzer":"ik_smart"
}
3.4 两种分词模式
IK提供了两个分词算法:ik_smart和ik_max_word
其中ik_smart为最少切分,ik_max_word为最细粒度划分
3.5 自定义词库
iK分词器自带的main.dic的文件为扩展词典,stopword.dic为停用词典。
- 修改配置文件:IKAnalyzer.cfg.xml
之后就可以通过修改main.dic文件内容实现自定义词库了
四. field详细介绍
ES6.2核心的字段类型如下:
4.1 field的属性介绍
4.1.1 type
- 通过type属性指定field的类型
"name":{
"type":"text"
}
4.1.2 analyzer
- 通过analyzer属性指定分词模式
"name": {
"type": "text",
"analyzer":"ik_max_word"
}
上边指定了analyzer是指在索引和搜索都使用ik_max_word,如果单独想定义搜索时使用的分词器则可以通过 search_analyzer属性。
对于ik分词器建议是索引时使用ik_max_word将搜索内容进行细粒度分词,搜索时使用ik_smart提高搜索精确性。
"name": {
"type": "text",
"analyzer":"ik_max_word",#生成索引目录时
"search_analyzer":"ik_smart"#检索时
}
4.2.1 index
通过index属性指定是否索引。 默认为index=true,即要进行索引,只有进行索引才可以从索引库搜索到。
"pic": {
"type":"text",
"index":false
}
4.3.1 source
如果某个字段内容非常多,业务里面只需要能对该字段进行搜索,比如:商品描述。查看文档内容会再次到mysql或者hbase中取数据,把大字段的内容存在Elasticsearch中只会增大索引,这一点文档数量越大结果越明显,如果一条文档节省几KB,放大到亿万级的量结果也是非常可观的。
-
如果只想存储某几个字段的原始值到Elasticsearch 可以通过incudes参数来设置,在mapping中的设置如下:
POST /java06/course/_mapping
{
"_source": {
"includes":["description"]
}
}
- 可以通过excludes参数排除某些字段
POST /java06/course/_mapping
{
"_source": {
"excludes":["description"]
}
}
4.2 常用field类型
4.2.1 text文本字段
例如:
- 创建新映射:
POST /java06/course/_mapping
{
"_source": {
"includes":["description"]
}
"properties": {
"name": {
"type": "text",
"analyzer":"ik_max_word",
"search_analyzer":"ik_smart"
},
"description": {
"type": "text",
"analyzer":"ik_max_word",
"search_analyzer":"ik_smart"
},
"pic":{
"type":"text",
"index":false
}
}
}
- 插入文档
POST /java06/course/1
{
"name":"python从入门到放弃",
"description":"人生苦短,我用Python",
"pic":"250.jpg"
}
- 查询测试
GET /java06/course/_search?q=name:放弃
GET /java06/course/_search?q=description:人生
GET /java06/course/_search?q=pic:250.jpg
结果:name和description都支持全文检索,pic不可作为查询条件
4.2.2 keyword关键字字段
keyword是按照整体搜索,所以创建keyword字段往索引目录写时是不进行分词的,比如:邮政编码、手机号码、身份证等。keyword字段通常用于过虑、排序、聚合等。
例如:
- 更改映射
POST /java06/course/_mapping
{
"properties": {
"studymodel":{
"type":"keyword"
}
}
}
- 插入文档
PUT /java06/course/2
{
"name": "java编程基础",
"description": "java语言是世界第一编程语言",
"pic":"250.jpg",
"studymodel": "2010年01月"
}
- 根据name查询文档
GET /java06/course/_search?q=studymodel:2010年01月
结果:name是keyword类型,所以查询方式是精确查询
4.2.3 data日期
日期类型不用设置分词器,通常日期类型的字段用于排序。 1)format 通过format设置日期格式,多个格式使用双竖线||分隔, 每个格式都会被依次尝试, 直到找到匹配的
例如:
- 设置允许date字段存储年月日时分秒、年月日及毫秒三种格式
POST /java06/course/_mapping
{
"properties": {
"timestamp": {
"type": "date",
"format": "yyyy-MM-dd"
}
}
}
- 插入文档
PUT /java06/course/3
{
"name": "spring开发基础",
"description": "spring 在java领域非常流行,java程序员都在用。",
"studymodel": "201001",
"pic":"250.jpg",
"timestamp":"2018-07-04 18:28:58"
}
4.2.4 Numeric类型
es中的数字类型经过分词(特殊)后支持排序和区间搜索
例如:
- 更新已有映射
POST /java06/course/_mapping
{
"properties": {
"price": {
"type": "float"
}
}
}
- 插入文档
PUT /java06/course/3
{
"name": "spring开发基础",
"description": "spring 在java领域非常流行,java程序员都在用。",
"studymodel": "201001",
"pic":"250.jpg",
"price":38.6
4.3 field属性的设置标准---根据标准设置
属性 | 标准 |
---|---|
type | 是否有意义 |
index | 是否搜索 |
source | 是否展示 |