ElasticSearch之入门

基本概念

ElasticSearch是面向文档
ElasticSearch(集群)中可以包含多个索引(数据库),每个索引中可以包含多个类型(表),
每个类型下又包含多个文档(行),每个文档包含多个字段

和关系型数据的对比 如下:

关系型数据库ElasticSearch
数据库(database)索引(indices)
表(tables)type 注:这个概念逐渐会被淘汰
行(rows)documents
字段(columns)fileds

分片

什么是分片

在ElasticSearch中,一个索引(库)被分为多个分片,分片用于存储数据,每个分片是一个Lucene的索引。所以一个ElasticSearch索引由多个Lucene索引组成

倒排索引
https://www.zhihu.com/question/23202010

倒排索引创建索引的流程:
1) 首先把所有的原始数据进行编号,形成文档列表
2) 把文档数据进行分词,得到很多的词条,以词条为key。包含这些词条的文档的编号为value 。
搜索的过程:
1)当用户输入任意的词条时,首先对用户输入的数据进行分词,得到用户要搜索的所有词条。
2)然后拿着这些词条去倒排索引列表中进行匹配。找到这些词条就能找到包含这些词条的所有文档的编号。
3)最后根据这些编号去文档列表中找到文档

IK分词器

两种分词模式:

  1. ik_smart:将文本做最粗粒度的拆分。如会将“中华人民共和国国歌”切分为“中华人民共和国”、“国歌”
  2. ik_max_word:将文本做最细粒度的拆分。如会将“中华人民共和国国歌”切分为“中华人民共和国”、“中华人民”、“中华”、“华人”、“人民共和国”、“人民”、“共和国”、“共和”、“国”、“国歌”

1. 如果不自定义分词,则无法切分出我们想要的词
在这里插入图片描述

2. 通过自定义分词,可以切分出我们想要的词

# 1. 进入es容器
[root@izuf6crq4k1mozjbsp7p09z config]# docker exec -it f2a7 /bin/bash
# 2. config/analysis-ik目录下有IKAnalyzer.cfg.xml配置文件和dic文件,dic文件中记录的是一个个默认的词
[root@f2a7e75092d4 elasticsearch]# cd config/analysis-ik/
[root@f2a7e75092d4 analysis-ik]# ls
IKAnalyzer.cfg.xml  extra_single_word.dic       extra_single_word_low_freq.dic   preposition.dic  stopword.dic  surname.dic
extra_main.dic      extra_single_word_full.dic  extra_stopword.dic              main.dic    quantifier.dic   suffix.dic
# 3. 新建自己的dic文件,里面写自定义的词
[root@f2a7e75092d4 analysis-ik]# touch jarvis.dic
[root@f2a7e75092d4 analysis-ik]# echo 姚一斌>>jarvis.dic   # 将姚一斌作为一个可搜索的词
# 4. 在IKAnalyzer.cfg.xml中配置自定义的dic文件
[root@f2a7e75092d4 analysis-ik]# cat IKAnalyzer.cfg.xml 
<?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">jarvis.dic</entry>  # 在这里加上自定义的dic文件
	 <!--用户可以在这里配置自己的扩展停止词字典-->
	<entry key="ext_stopwords"></entry>
	<!--用户可以在这里配置远程扩展字典 -->
	<!-- <entry key="remote_ext_dict">words_location</entry> -->
	<!--用户可以在这里配置远程扩展停止词字典-->
	<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
# 5. 退出es容器,重启es容器和kibana容器

在这里插入图片描述

Rest风格操作

methodurl地址描述
PUTlocalhost:9200/索引名称/类型名称/文档id创建文档(指定文档 id)
POSTlocalhost:9200/索引名称/类型名称创建文档(随机文档 id)
POSTlocalhost:9200/索引名称/类型名称/文档id/_update修改文档
DELETElocalhost:9200/索引名称/类型名称/文档id删除文档
GETlocalhost:9200/索引名称/类型名称/文档id通过文档id查询文档
POSTlocalhost:9200/索引名称/类型名称/_search查询所有数据

1. _cat

GET  /_cat/nodes :查看所有节点
GET  /_cat/health :查看es健康状况
GET  /_cat/master : 查看主节点
GET  /_cat/indices : 查看所有索引
GET  /_cat/indices?v :查看所有索引(带表头)

2. PUT/POST新建文档

# 创建指定id的文档  
#   注: 1. 如果索引不存在,则也会创建索引 
#       2. 如果创建的索引没有显式地指定字段类型,则会根据添加的值确定字段默认的类型
PUT /jarvis_indice/jarvis_type/1   # type默认为_doc,且type逐渐被弃用 会有提示:use the /{index}/_doc/{id}
{
  "name":"jarvis",
  "age":24
}
PUT /jarvis_indice/_doc/2  # 将type改为_doc,则此时不会有提示
{
  "name":"jarvis",
  "age":24,
  "birthday":"1996-05-01"
}
# 获取文档
GET /jarvis_indice/_doc/2
===output:
{
  "_index" : "jarvis_indice",  //该条数据所在的索引
  "_type" : "_doc",   //数据类型
  "_id" : "2",   //id
  "_version" : 1,   //数据的版本
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "jarvis",
    "age" : 24,
    "birthday" : "1996-05-01"
  }
}
==============================================
# POST创建不指定id的文档  
#   注:当POST方式且不指定id,多次重复创建相同数据的文档,id也是不同的,即每次POST,都是创建不同的文档
POST /jarvis_indice/_doc
{
  "name":"robin",
  "age":23,
  "birthday":"1996-06-17"
}
===output:
{
  "_index" : "jarvis_indice",
  "_type" : "_doc",
  "_id" : "HR_JS3cB9kPBMfNjArcI",  //自动生成唯一id
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 3,
  "_primary_term" : 1
}
=========================================
# POST创建指定id的文档   效果和PUT一样

3. PUT/POST修改文档

# 修改文档--方式1   
#   注: 1. 相当于覆盖原有的文档。弊端在于,如果现有的文档少了某个字段如birthday,则修改后该字段就会没有
#       2. 第一次PUT,即新增一个文档;多次PUT,_version会变,即数据版本会改变
PUT /jarvis_indice/_doc/2
{
  "name":"jarvisss",
  "age":25 
}
===output:
{
  "_index" : "jarvis_indice",
  "_type" : "_doc",
  "_id" : "2",
  "_version" : 2,  //版本为2
  "result" : "updated",  //表示该数据被修改
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 7,
  "_primary_term" : 1
}
GET /jarvis_indice/_doc/2
===output:
{
  "_index" : "jarvis_indice",
  "_type" : "_doc",
  "_id" : "2",
  "_version" : 2,
  "_seq_no" : 2,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "jarvisss",
    "age" : 25   //少了birthday字段
  }
}
========================================================
# 修改文档--方式2
# 这种方式不是覆盖更新,而是更新写出来的字段数据
# 如果要更新的数据和原有数据一致,则不会进行更新,version和_seq_no不变,result为noop(无操作)
POST /jarvis_indice/_doc/2/_update
{
  "doc":{
    "name":"jarviaaa",
    "age":26,
    "birthday":"1996-07-01"
  }
}
GET /jarvis_indice/_doc/2
===output:
{
  "_index" : "jarvis_indice",
  "_type" : "_doc",
  "_id" : "2",
  "_version" : 3,
  "_seq_no" : 2,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "jarviaaa",
    "age" : 26,
    "birthday" : "1996-07-01"
  }
}
数据不变,多次更新  POST /jarvis_indice/_doc/2/_update
{
  "_index" : "jarvis_indice",
  "_type" : "_doc",
  "_id" : "2",
  "_version" : 3,  //版本不变
  "result" : "noop",  //noop为无操作
  "_shards" : {
    "total" : 0,
    "successful" : 0,
    "failed" : 0
  },
  "_seq_no" : 2,
  "_primary_term" : 1
}

PUT和POST总结:

PUT:
1.必须带id
2.第一次PUT则新增一个文档
3.如果该id的文档已有,则覆盖更新(如果现有文档字段比原有文档少,则更新后该字段不存在)
POST:
1.如果不带id,每次都是新增一个文档,且自动生成唯一id
2.如果带id ,更新和修改都和PUT效果一样
3.indice/_doc/id/_update:不是覆盖更新,而是只更新写出来的字段数据;且如果数据和原有数据一致,则不作更新

4. DELETE 删除索引/文档

DELETE jarvis_indice/_doc/2  删除文档
DELETE jarvis_indice         删除索引

5. GET查询

GET /jarvis_indice/_doc/2
===output:
{
  "_index" : "jarvis_indice",  //在哪个索引 
  "_type" : "_doc",    //在哪个类型
  "_id" : "2",   //文档id
  "_version" : 3,  //版本号
  "_seq_no" : 2,  //并发控制字段,每次更新就会+1,用来做乐观锁  
  "_primary_term" : 1,  //并发控制字段
  "found" : true,
  "_source" : {
    "name" : "jarviaaa",
    "age" : 26,
    "birthday" : "1996-07-01"
  }
}
乐观锁操作,更新的时候在url后携带:?if_seq_no=X1&if_primary_term=X2

6. bulk批量API

POST /jarvis_indice/_doc/_bulk   批量增加三条数据,这三条命令都是独立的
{"index":{"_id":11}}
{"name":"jarvis01"}
{"index":{"_id":12}}
{"name":"jarvis02"}
{"index":{"_id":13}}
{"name":"jarvis03"}

批量导入数据:
https://github.com/elastic/elasticsearch/blob/master/docs/src/test/resources/accounts.json

7. QueryDSL

一种可以查询的Json风格的DSL(domain-specific language领域特定语言)

===常用格式:
GET /bank/_search   #  格式:GET /索引名/_search {请求体}
{
  "query": {     //查询条件
    "match_all": {}    
  },
  "sort": [      //排序
    {
      "balance": {
        "order": "desc"
      }
    }
  ],
  "from": 5,   //从第5条开始
  "size": 5,   //取5条
  "_source": ["balance","address"]  //只查这些字段
}

query中的查询方式:
1. match_all 表示查所有  
2. match 表示根据条件查询:如果字段不是字符串类型,则精确匹配;如果是文本,则模糊匹配
3. match_phrase 将检索条件当成一个整体,不进行分词
4. keyword匹配  将检索条件当成一个整体,不进行分词,且为精确等值匹配
5. multi_match 多字段匹配
6. bool复合查询
7. term查询 可以使用term来查询条件字段为精确值的文档
8. aggregation聚合

===match匹配
{
  "query": {
    "match": {
      "address": "671 Street"  //会对检索条件进行分词,如这里,会被切分成671和Street,
                               //则address中带有671或Street的文档都可以被查出来
    }
  }
}
===match_phrase匹配
{
  "query": {
    "match_phrase": {
      "address": "Bristol Street"  //不会对检索条件进行分词,即要匹配出address中包含"Bristol Street"的文档,
                                   //故此可以匹配出"671 Bristol Street"
    }
  }
}
===keyword匹配
{
  "query": {
    "match": {
      "address.keyword": "Bristol Street"  //不会对检索条件进行分词,且进行精确等值匹配,即要匹配出
                                           //address等于"Bristol Street"的文档,故此无法匹配出"671 Bristol Street"
    }
  }
}
===multi_match匹配
{
  "query": {
    "multi_match": {
      "query": "mill Wanamie",   //会对检索条件进行分词
      "fields": ["address","city"]   //address或city两个字段中只要有一个包
                                     //含"mill""Wanamie",则可被查出
    }
  }
}
===bool查询    must  must_not   should   filter
{
  "query": {
    "bool": {   //bool多条件组合查询
      "must": [    //must表示必须满足的条件,数组中可写多条件
        {"match": {
          "gender": "F"
        }},
        {"match": {
          "address": "Street"
        }}
      ],
      "must_not": [   //must_not表示必须不满足的条件,数组中可写多条件
        {"match": {
          "age": 23
        }}
      ],
      //应该满足的条件,不改变查询的结果集,
      //但是可以提高满足这个条件的文档的相关性得分score(即可以改变结果集中文档的顺序)
      "should": [   
        {"match": {
          "city": "Jacksonburg"
        }}
      ],
      //filter可以对查询结果进行过滤。只过滤,不会改变相关性得分score的值
      "filter": {   
        "range": {
          "age": {
            "gte": 20,
            "lte": 50
          }
        }
      }
    }
  }
}
===term查询
{
  "query": {
    "term": {
      "age": {
        "value": 32   //term不能用来检索字段为text文本的条件
      }
    }
  }
}
最好:全文检索字段使用match,其他非text字段使用term

===aggregation聚合  
1. 按照年龄聚合,并且计算每个年龄的人的平均薪资
GET /bank/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {   //第一次聚合:聚合不同年龄的人
    "ageAgg": {
      "terms": {
        "field": "age",
        "size": 100
      },
      "aggs": {                  //第二次聚合:对第一次聚合的结果再次聚合,写在第一个aggs里。
        "everyAgeBalanceAvg": {  //对每个年龄的人群的平均工资进行计算
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}
2. 查出所有年龄分布,并且这些年龄段中gender为M的平均薪资、gender为F的平均薪资、这个年龄总的平均薪资
GET /bank/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {    //第一次聚合:聚合不同年龄的人
    "ageAgg": {
      "terms": {
        "field": "age",
        "size": 100
      },
      "aggs": {   //该聚合中有两个同级的子聚合
        "genderAgg": {   //聚合每个年龄中不同性别的平均薪资
          "terms": {
            "field": "gender.keyword"
          },
          "aggs": {
            "balanceAvg": {
              "avg": {
                "field": "balance"
              }
            }
          }
        },
        "everyAgeBalanceAvg": {  //聚合每个年龄总的平均薪资
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}

在这里插入图片描述

8. Mapping

# 获取索引映射规则
GET 索引/_mapping
# 创建索引时指定字段映射规则
PUT /test_indice
{
  "mappings": {
    "properties": {
      "name":{
        "type": "text"  
      },
      "age":{
        "type": "integer"
      },
      "birthday":{
        "type": "date"
      }"email":{
        "type": "keyword"  //类型设置为keyword,表示不分词且进行精确等值匹配
      }
    }
  }
}
# 给已有索引添加新的字段映射
PUT test_indice/_mapping
{
  "properties":{
    "emplo_id":{
      "type":"integer",
      "index":false   
      //index默认都为true,表示都可以作为搜索条件;
      //设为false,表示该字段不能作为搜索的条件
    }
  }
}
# 对于已存在的字段映射无法进行更新,只能重建一个索引,然后数据迁移
POST _reindex   //迁移数据
{
  "source": {   //原索引
    "index": "bank"
  },
  "dest": {     //目标索引
    "index": "new_bank"
  }
}

类型为keyword

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值