ElasticSearch全文检索
基本概念
- 索引index
动词,相当于mysql的insert
名词,相当于mysql的databse
- 类型type
在index索引中,可以定义一个或者多个类型
类似于mysql的table,每一种类型的数据放在一起
- 文档Document
文档是json格式
- 倒排索引
Docker安装ES环境
docker pull elasticsearch:7.17.17 #存储和检索数据
docker pull kibana:7.17.17 #可视化检索数据
创建挂载目录~/tools/docker-volumes/elasticsearch
:
- config文件夹,里面放一个
elasticsearch.yml
文件,写入http.host: 0.0.0.0
注意冒号后面要加空格 - data文件夹
运行容器
docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
-v ~/tools/docker-volumes/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v ~/tools/docker-volumes/elasticsearch/data:/usr/share/elasticsearch/data \
-v ~/tools/docker-volumes/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.17.17
访问:http://localhost:9200/,看到下面界面成功
运行kibana:
docker run --name kibana -e ELASTICSEARCH_HOSTS="http://192.168.1.11:9200" -p 5601:5601 \
-d kibana:7.17.17
注意:
ip不可以使用localhost,否则会一直出现Kibana server is not ready yet
使用ifconfig查看本机ip
初步检索
- cat
GET http://localhost:9200/_cat/nodes 查看所有节点
GET http://localhost:9200/_cat/health 查 看es健康状况
GET http://localhost:9200/_cat/master 查看主节点信息
GET http://localhost:9200/_cat/indices 查看所有的索引
- 索引文档(保存)POST/PUT
PUT http://localhost:9200/customer/external/1
{
"name": "John Doe"
}
PUT 和 POST 都可以,
- POST 新增。如果不指定 id,会自动生成 id。指定 id 就会修改这个数据,并新增版本号PUT 可以新增可以修改。
- PUT 必须指定 id;由于 PUT 需要指定 id,我们一般都用来做修改操作,不指定 id 会报错。
- 查询文档GET
{
"_index": "customer", //在哪个索引
"_type": "external", //在哪个类型
"_id": "1", //记录 id
"_version": 2, //版本号
"_seq_no": 1, //并发控制字段,每次更新就会+1,用来做乐观锁
"_primary_term": 1, //同上,主分片重新分配,如重启,就会变化
"found": true,
"_source": { //真正的内容
"name": "John Doe"
}
}
- 更新文档POST/PUT
POST customer/external/1/_update
{
"doc": {
"name": "John Doew"
}
}
或者:
POST customer/external/1
{
"name": "John Doe2"
}
POST 操作会对比源文档数据,如果相同不会有什么操作,文档version 不增加
PUT 操作总会将数据重新保存并增加 version 版本;
带_update 对比元数据如果一样就不进行任何操作
或者:
PUT customer/external/1
{
"name": "John Doe"
}
- 删除DELETE
删除文档
DELETE customer/external/1
删除索引
DELETE customer
- bulk批量API
POST /customer/external/_bulk
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }
使用kibana
复杂操作:
POST /_bulk
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title": "My first blog post" }
{ "index": { "_index": "website", "_type": "blog" }}
{ "title": "My second blog post" }
{ "update": { "_index": "website", "_type": "blog", "_id": "123" } }
{ "doc" : {"title" : "My updated blog post"} }
测试数据:
https://github.com/elastic/elasticsearch/blob/7.4/docs/src/test/resources/accounts.json
POST /bank/account/_bulk
+数据
进阶检索
SearchAPI
- 请求方式检索:
GET bank/_search?q=*&sort=account_number:asc
- uri+请求体进行检索
GET bank/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"account_number": {
"order": "desc"
}
},
{
"balance": "desc"
}
]
}
Query DSL
基本语法:
GET bank/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"balance": {
"order": "desc"
}
}
],
"from": 1,
"size": 3,
"_source": ["balance","firstname"]
}
说明:
GET bank/_search
: 这是Elasticsearch中执行搜索操作的基本语法。正在请求bank
索引中的文档。"query": {"match_all": {}}
: 这个查询部分指定了搜索的条件。在这里,使用了match_all
查询,表示你想要匹配所有文档,即检索所有数据。"sort": [{"balance": {"order": "desc"}}]
: 这个部分用于对结果进行排序。希望按照balance
字段降序排序,这意味着余额最高的文档将排在前面。"from": 1
: 这个参数指定了从搜索结果的第几条文档开始返回。在这里,从第二条文档开始返回(因为Elasticsearch使用0-based索引)。"size": 3
: 这个参数定义了返回的文档数量,即最多返回3条匹配的文档。"_source": ["balance", "firstname"]
: 这个参数用于指定返回结果中包含的字段。在这里,只关心balance
和firstname
字段的值,其他字段将不会包含在结果中。
match匹配查询:
- 基本类型,非字符串精确匹配
GET /bank/_search
{
"query": {
"match": {
"account_number": "20"
}
}
}
- 字符串,全文检索(倒排索引)计算相关性得分
GET /bank/_search
{
"query": {
"match": {
"address": "mill"
}
}
}
- 字符串,分词检索
GET /bank/_search
{
"query": {
"match": {
"address": "mill road"
}
}
}
- match_phrase短语匹配
GET /bank/_search
{
"query": {
"match_phrase": {
"address": "mill road"
}
}
}
和上面的区别是:
- match_phrase 匹配 必须包含
mill road
- match匹配
mill
或者road
或者mill road
- multi_match 多字段匹配
GET /bank/_search
{
"query": {
"multi_match": {
"query": "mill",
"fields": ["state","address"]
}
}
}
- bool复合查询
must必须达到的所有条件
GET /bank/_search
{
"query": {
"bool": {
"must": [
{"match": {"address": "mill"}},
{"match": {"gender": "M"}}
]
}
}
}
should:应该达到的条件,符合会加分
GET /bank/_search
{
"query": {
"bool": {
"must": [
{"match": {"address": "mill"}},
{"match": {"gender": "M"}}
],
"should": [
{"match": {
"address": "lane"
}}
]
}
}
}
must_not必须不是指定的情况:
GET /bank/_search
{
"query": {
"bool": {
"must": [
{"match": {"address": "mill"}},
{"match": {"gender": "M"}}
],
"should": [
{"match": {
"address": "lane"
}}
],
"must_not": [
{"match": {
"email": "baluba.com"
}}
]
}
}
}
- filter结果过滤
GET /bank/_search
{
"query": {
"bool": {
"must": [
{"match": {
"address": "mill"
}}
],
"filter": [
{"range": {
"balance": {
"gte": 10000,
"lte": 20000
}
}}
]
}
}
}
- term,匹配某个属性的值,精确匹配
全文检索字段用match,其他非text用term
GET /bank/_search
{
"query": {
"bool": {
"must": [
{"term": {
"age": {
"value": "28"
}
}
}
]
}
}
}
- aggregations执行聚合
GET /bank/_search
{
"query": {
"match": {
"address": "mill"
}},
"aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 10
}
},
"ageAvg":{
"avg": {
"field": "age"
}
},
"balanceAvg":{
"avg": {
"field": "balance"
}
}
},
"size": 0
}
"aggs": {...}
: 这是聚合部分,用于对结果进行汇总分析。
"ageAgg": {...}
: 这是一个名为ageAgg
的聚合,使用了terms聚合,它将文档按照age
字段的值分组,并且设置了size
为10,表示只返回前10个分组。"ageAvg": {...}
: 这是计算age
字段的平均值的聚合。"balanceAvg": {...}
: 这是计算balance
字段的平均值的聚合。"size": 0
: 这个参数表示不返回文档,只返回聚合结果。
复杂聚合:
查年龄分布和这个年龄的平均薪资
GET /bank/_search
{
"query": {
"match_all": {}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 100
},
"aggs": {
"ageAvg": {
"avg": {
"field": "balance"
}
}
}
}
}
}
查出所有年龄分布,并且这些年龄段中M的平均薪资和F的平均薪资以及这个年龄段的总体平均薪资
GET /bank/_search
{
"query": {"match_all": {}}
, "aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 100
},
"aggs": {
"genderAgg": {
"terms": {
"field": "gender.keyword",
"size": 10
}
,
"aggs": {
"balanceAgg": {
"avg": {
"field": "balance"
}
}
}
},
"ageBalanceAvg":{
"avg": {
"field": "balance"
}
}
}
}
}
}
Mapping映射
创建时可以指定字段的类型
PUT /my_index
{
"mappings": {
"properties": {
"age":{
"type": "integer"
},
"email":{
"type": "keyword"
},
"name":{
"type": "text"
}
}
}
}
添加新的映射:
PUT /my_index/_mapping
{
"properties":{
"employee_id":{
"type":"keyword",
"index":false
}
}
}
更新:
索引不可以更新,只可以重新创建
数据迁移:
POST _reindex
{
"source": {
"index": "bank",
"type": "account"
},
"dest": {
"index": "newbank"
}
}