栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 软件开发 > 后端开发 > Java

ElasticSearch

Java 更新时间:发布时间: 百科书网 趣学号
ElasticSearch 一、基本入门 1、RESTFUL、JSON

Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。

全文搜索引擎

​ 根据关键字生成索引,我们在搜索的时候输入关键字,它们会将该关键字即索引匹配到的所有网页返回

RESTFUL

​ RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义。RESTFUL适用于移动互联网厂商作为业务接口的场景,实现第三方OTT调用移动网络资源的功能,动作类型为新增、变更、删除所调用资源。

RESTFUL特点包括:

1、每一个URI代表1种资源;

2、客户端使用GET、POST、PUT、DELETe4个表示操作方式的动词对服务端资源进行操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源;

3、通过操作资源的表现形式来操作资源;

4、资源的表现形式是XML或者HTML;

5、客户端与服务端之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都必须包含理解请求所必需的信息。

JSON 语法规则

JSON 语法是 Javascript 对象表示语法的子集。

  • 数据在名称/值对中

  • 数据由逗号分隔

  • 大括号 {} 保存对象

  • 中括号 [] 保存数组,数组可以包含多个对象

  • JSON 数据的书写格式是:

    key : value
    
{
   "name":"张三","age":18
}

JSON数组

{
	"students":[
        {"name":"张三","age":18},
        {"name":"李四","age":20},
		{"name":"王五","age":22}
    ]
}

正排索引(传统)

idcontent
1001my name is zhang san
1002my name is li si

倒排索引

keywordid
name1001, 1002
zhang1001

Elasticsearch 是面向文档型数据库,一条数据在这里就是一个文档。

Index(索引)

类比MySQL,Index相当于数据库。

动词,相当于 MySQL 中的 insert;

名词,相当于 MySQL 中的 Database
Type(类型)

类比MySQL,Type相当于数据表。

在 Index(索引)中,可以定义一个或多个类型。

类似于 MySQL 中的 Table;每一种类型的数据放在一起;
document(文档)

类比MySQL,document相当于数据。

保存在某个索引(Index)下,某种类型(Type)的一个数据(document),文档是 JSON 格式的,document 就像是 MySQL 中的某个 Table 里面的内容;

2、docker安装ElasticSearch

1、拉取镜像

docker pull elasticsearch:7.8.0

2、创建文件

mkdir -p /mydata/elasticsearch/config
mkdir -p /mydata/elasticsearch/data
echo "http.host: 0.0.0.0">>/mydata/elasticsearch/config/elasticsearch.yml

3、提升文件权限

chmod -R 777 /mydata/elasticsearch/

4、启动容器

docker run --name elasticsearch -p 9200:9200 
 -p 9300:9300 
 -e "discovery.type=single-node" 
 -e ES_JAVA_OPTS="-Xms64m -Xmx128m" 
  -v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml 
 -v /mydata/elasticsearch/data:/usr/share/elasticsearch/data 
 -v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins 
 -d elasticsearch:7.8.0

参数说明

--name elasticsearch:将容器命名为 elasticsearch
-p 9200:9200:将容器的9200端口映射到宿主机9200端口
-p 9300:9300:将容器的9300端口映射到宿主机9300端口,目的是集群互相通信
-e "discovery.type=single-node":单例模式
-e ES_JAVA_OPTS="-Xms64m -Xmx128m":配置内存大小
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:将配置文件挂载到宿主机
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data:将数据文件夹挂载到宿主机
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins:将插件目录挂载到宿主机(需重启)
-d elasticsearch:7.7.0:后台运行容器,并返回容器ID

5、阿里云开启9200,9300daunkou

6、测试

47.108.170.87:9200
返回结果
	
name	"e9c6802b4542"
cluster_name	"elasticsearch"
cluster_uuid	"dWtRimy5SA-S-co2fOBkcA"
version	
number	"7.8.0"
build_flavor	"default"
build_type	"docker"
build_hash	"757314695644ea9a1dc2fecd26d1a43856725e65"
build_date	"2020-06-14T19:35:50.234439Z"
build_snapshot	false
lucene_version	"8.5.1"
minimum_wire_compatibility_version	"6.8.0"
minimum_index_compatibility_version	"6.0.0-beta1"
tagline	"You Know, for Search"

7、docker容器自启动

docker update elasticsearch --restart=always
3、docker安装Kibana

Kibana是一个开源的分析与可视化平台,设计出来用于和Elasticsearch一起使用的。你可以用kibana搜索、查看存放在Elasticsearch中的数据。Kibana与Elasticsearch的交互方式是各种不同的图表、表格、地图等,直观的展示数据,从而达到高级的数据分析与可视化的目的。
Elasticsearch、Logstash和Kibana这三个技术就是我们常说的ELK技术栈,可以说这三个技术的组合是大数据领域中一个很巧妙的设计。一种很典型的MVC思想,模型持久层,视图层和控制层。Logstash担任控制层的角色,负责搜集和过滤数据。Elasticsearch担任数据持久层的角色,负责储存数据。而我们这章的主题Kibana担任视图层角色,拥有各种维度的查询和分析,并使用图形化的界面展示存放在Elasticsearch中的数据。

3.1 docker 拉取kibana镜像,与Elasticsearch版本一致

docker pull kibana:7.8.0

3.2启动容器

docker run --name kibana -e ELASTICSEARCH_HOSTS=http://47.108.170.87:9200 -p 5601:5601 -d kibana:7.8.0
3.3测试

http://47.108.170.87:5601

谷歌浏览器安装postman插件

火狐浏览器安装RESTClient和 HttpRequester 插件

二、CRUD

get一般是获取,put创建,delete删除,

基本了解

_cat/nodes 查看所有节点

_cat/master 查看住节点

_cat/health 查看es健康状态

_cat/indices 查看所有索引 (相当于查看数据库里面的所有数据库)

put请求保存一个数据,保存在哪个索引的哪个类型下,指定用哪个唯一标识

数据库 test 库,student表,1是主键

es:/test/student/1

test是索引==数据库

student 是类型 == 数据表

POST 新增。如果不指定 id,会自动生成 id。指定 id 就会修改这个数据,并新增版本号

PUT 可以新增可以修改。PUT 必须指定 id;由于 PUT 需要指定 id,我们一般都用来做修改操作,不指定 id 会报错。

post可以获得某类型下的所有数据/test/student

get必须加上id获得数据/test/student/1

post提交修改数据/test/student/2/_update

body为新数据

{
"doc":{
    "id": 31,
    "name": "何迪5201314",
     "age": 20
	}
}

delete请求删除数据/test/student/1

删除

index是test

type是student

id是_upJJXwBXMdUiOLkZ2Sk

批量bulk

POST test/studnet/_bulk
{"index":{"_id":"1"}}
{	"id": 1,
	"name": "王一辉",
	"age":18
}
{"index":{"_id":"2"}}
{	"id": 2,
	"name": "何迪",
	"age":18
}

1、创建索引
http://47.108.170.87:9200/shopping #put sent

返回结果

{
    "acknowledged": true,         //响应结果
    "shards_acknowledged": true,  //分片结果
    "index": "shopping"           //索引名称
}

再次发送报错

{
    "error": {
        "root_cause": [
            {
                "type": "resource_already_exists_exception",
                "reason": "index [shopping/uRoeuSIBSb2ntHSkg37gMw] already exists",
                "index_uuid": "uRoeuSIBSb2ntHSkg37gMw",
                "index": "shopping"
            }
        ],
        "type": "resource_already_exists_exception",
        "reason": "index [shopping/uRoeuSIBSb2ntHSkg37gMw] already exists",
        "index_uuid": "uRoeuSIBSb2ntHSkg37gMw",
        "index": "shopping"
    },
    "status": 400
}
2、查看所有索引
http://47.108.170.87:9200/_cat/indices   //get sent

返回结果

health status index    uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   shopping uRoeuSIBSb2ntHSkg37gMw   1   1          0            0       208b           208b

_cat查看;indices所有索引

相当于MySQL的show tables;

表头 含义
health 当前服务器健康状态: green(集群完整) yellow(单点正常、集群不完整) red(单点不正常)
status 索引打开、关闭状态
index 索引名
uuid 索引统一编号
pri 主分片数量
rep 副本数量
docs.count 可用文档数量
docs.deleted 文档删除状态(逻辑删除)
store.size 主分片和副分片整体占空间大小
pri.store.size 主分片占空间大小

3、查看单个索引
http://47.108.170.87:9200/shopping   //get sent

返回结果

{
    "shopping": {                                  //索引名
        "aliases": {},                             //别名
        "mappings": {},                            //映射
        "settings": {                              //设置
            "index": {                             //设置索引
                "creation_date": "1627440132306",  //索引-创建时间
                "number_of_shards": "1",           //索引-分片
                "number_of_replicas": "1",         //索引-分片
                "uuid": "uRoeuSIBSb2ntHSkg37gMw",  //索引-id
                "version": {
                    "created": "7080099"
                },
                "provided_name": "shopping"        //索引-名字
            }
        }
    }
}
4、删除索引
http://47.108.170.87:9200/shopping    #delete sent

返回结果

{
    "acknowledged": true
}
5、创建文档

文档是建立在索引下面的

http://47.108.170.87:9200/shopping/_doc    //POST Sent

body内容

{
    "title":"小米手机",
    "category":"小米",
    "images":"http://www.gulixueyuan.com/xm.jpg",
    "price":3999.00
}

返回结果

{
    "_index": "shopping",
    "_type": "_doc",
    "_id": "bYMi63oBSIJIs80cgCJH",
    "_version": 1,
    "result": "created",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 0,
    "_primary_term": 1
}
6、查询文档全部
http://47.108.170.87:9200/shopping/_doc/1    //GET Sent

返回结果

{
    "_index": "shopping",
    "_type": "_doc",
    "_id": "1",
    "_version": 4,
    "_seq_no": 4,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "title": "小米机",
        "category": "小米",
        "images": "http://www.gulixueyuan.com/xm.jpg",
        "price": 3999
    }
}s

7、查询某个索引下的全部数据

http://47.108.170.87:9200/shopping/_search    //GET Sent

注意:

要把上次创建body里面的内容删除了

8、全量修改

http://47.108.170.87:9200/shopping/_doc/1    //POST   Sent

body内容:

{
    "title":"华为手机",
    "category":"华为",
    "images":"http://www.gulixueyuan.com/hw.jpg",
    "price":1999.00
}

返回结果:

{
    "_index": "shopping",
    "_type": "_doc",
    "_id": "1",
    "_version": 5,
    "result": "updated",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 5,
    "_primary_term": 1
}
7、局部修改
http://47.108.170.87:9200/shopping/_update/1      //Post Sent

body内容:

{
	"doc": {
		"title":"苹果手机",
		"category":"苹果"
	}
}

返回结果

{
    "_index": "shopping",
    "_type": "_doc",
    "_id": "1",
    "_version": 6,
    "result": "updated",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 6,
    "_primary_term": 1
}

8、删除
http://47.108.170.87:9200/shopping/_doc/1    //DELETE Sent

返回结果

{
    "_index": "shopping",
    "_type": "_doc",
    "_id": "1",
    "_version": 7,
    "result": "deleted",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 7,
    "_primary_term": 1
}
9、条件查询

url带参

http://47.108.170.87:9200/shopping/_search?q=category:红   //GET Sent

category包含红的

请求体

http://47.108.170.87:9200/shopping/_search               //GET Sent
{
	"query":{
		"match":{
			"category":"红米"
		}
	}
}

注意

我们要查询的是红米,它会单个字拆开进行模糊查询,查出包含红或米的数据

10、全部查询

请求体方式

http://47.108.170.87:9200/shopping/_search               //GET Sent

{
	"query":{
		"match_all":{}
	}
}

11、查询制定字段数据
http://47.108.170.87:9200/shopping/_search               //GET Sent

{
	"query":{
		"match_all":{}
	},
	"_source":["title"]
}

12、分页查询
http://47.108.170.87:9200/shopping/_search               //GET Sent

{
	"query":{
		"match_all":{}
	},
	"from":0,
	"size":2
}

13、排序查询
http://47.108.170.87:9200/shopping/_search               //GET Sent

{
	"query":{
		"match_all":{}
	},
	"sort":{
		"price":{
			"order":"desc"
		}
	}
}

手机价格降序

14、多条件查询
http://47.108.170.87:9200/shopping/_search               //GET Sent

查询手机牌子是小米和价格是3999的手机

{
	"query":{
		"bool":{
			"must":[{
				"match":{
					"category":"小米"
				}
			},{
				"match":{
					"price":3999.00
				}
			}]
		}
	}
}
15、范围查询
http://47.108.170.87:9200/shopping/_search               //GET Sent

价格是大于2000的小米手机或者华为手机

{
	"query":{
		"bool":{
			"should":[{
				"match":{
					"category":"小米"
				}
			},{
				"match":{
					"category":"华为"
				}
			}]
		},
        "filter":{
            "range":{
                "price":{
                    "gt":2000
                }
            }
        }
	}
}

三、进阶检索

查询某个type下的所有数据

get 请求/test/student/_search 查询所有

四、Query DSL

一个查询语句 的典型结构

{
	"QUERY_NAME":{ 
		"ARGUMENT": "VALUE",
    	"ARGUMENT1": "VALUE1",...
    }
}

针对某个字段

{
    "QUERY_NAME":{
        "FIELD_NAME":{
            "ARGUMENT":"VALUE",
            "ARGUMENT1":"VALUE1"...
        }
    }
}

1、返回部分字段
GET bank/_search
{
  "_source": ["balance","firstname"]
}

使用"_source"规定返回的字段名称

2、 match【匹配查询】
基本类型(非字符串),精确匹配

GET bank/_search
{
  "query": {
    "match": {
      "account_number": "20"
    }
  }
}

match 返回 account_number=20 的

字符串,全文检索

GET bank/_search
{
    "query":{
        "match":{
            "address":"mill"
        }
    }
}


最终查询出 address 中包含 mill 单词的所有记录

match 当搜索字符串类型的时候,会进行全文检索,并且每条记录有相关性得分。

字符串,多个单词(分词+全文检索)

GET bank/_search
{
    "query":{
        "match":{
            "address":"mill road"
        }
    }
}


最终查询出 address 中包含 mill 或者 road 或者 mill road 的所有记录,并给出相关性得分

全文检索最终会按照评分进行排序,会对检索条件进行分词匹配
3、match_phrase【短语匹配】

将需要匹配的值当成一个整体单词(不分词)进行检索

GET bank/_search
{
    "query":{
        "match_phrase":{
            "address":"mill road"
        }
    }
}

查出 address 中包含 mill road 的所有记录,并给出相关性得分

4、 multi_match【多字段匹配】
GET bank/_search
{
    "query":{
        "multi_match":{
            "query":"mill",
            "fields":[
                "state",
                "address"
            ]
        }
    }
}

查询的是state或者address中包含mill字段的

在这里插入图片描述

5、bool【复合查询】

bool 用来做复合查询:

复合语句可以合并 任何 其它查询语句,包括复合语句,了解这一点是很重要的。这就意味着,复合语句之间可以互相嵌套,可以表达非常复杂的逻辑。

must:必须达到 must 列举的所有条件

GET bank/_search
{
    "query":{
        "bool":{
            "must":[
                {
                    "match":{
                        "address":"mill"
                    }
                },
                {
                    "match":{
                        "gender":"M"
                    }
                }
            ]
        }
    }
}
在这里插入图片描述

should:应该达到 should 列举的条件,如果达到会增加相关文档的评分,并不会改变查询的结果。如果 query 中只有 should 且只有一种匹配规则,那么 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"
                    }
                }
            ]
        }
    }
}
在这里插入图片描述

address 包含 mill,并且 gender 是 M,如果 address 里面有 lane 最好不过,但是 email 必

须不包含 baluba.com

在这里插入图片描述
6、 filter【结果过滤】

并不是所有的查询都需要产生分数,特别是那些仅用于 “filtering”(过滤)的文档。为了不计算分数 Elasticsearch 会自动检查场景并且优化查询的执行。

过滤不会计算相关性得分,只会筛选出满足条件的数据。

GET bank/_search
{
    "query":{
        "bool":{
            "must":[
                {
                    "match":{
                        "address":"mill"
                    }
                }
            ],
            "filter":{
                "range":{
                    "balance":{
                        "gte":10000,
                        "lte":20000
                    }
                }
            }
        }
    }
}
7、 term和 match 一样。匹配某个属性的值。

全文检索字段用 match,其他非 text 字段匹配用 term。

在这里插入图片描述

GET bank/_search
{
    "query":{
        "bool":{
            "must":[
                {
                    "term":{
                        "age":{
                            "value":"28"
                        }
                    }
                },
                {
                    "match":{
                        "address":"990 Mill Road"
                    }
                }
            ]
        }
    }
}
8、ggregations(执行聚合)

聚合提供了从数据中分组和提取数据的能力。最简单的聚合方法大致等于 SQL GROUP

BY 和 SQL 聚合函数。在 Elasticsearch 中,您有执行搜索返回 hits(命中结果),并且同时返回聚合结果,把一个响应中的所有 hits(命中结果)分隔开的能力。这是非常强大且有效的, 您可以执行查询和多个聚合,并且在一次使用中得到各自的(任何一个的)返回结果,使用一次简洁和简化的 API 来避免网络往返。

搜索address中包含mill的所有人的年龄分布以及平均年龄,但不显示这些人的详情。

GET bank/_search
{
    "query":{
        "match":{
            "address":"mill"
        }
    },
    "aggs":{
        "group_by_state":{
            "terms":{
                "field":"age"
            }
        },
        "avg_age":{
            "avg":{
                "field":"age"
            }
        }
    },
    "size":0
}

size:0 不显示搜索数据

aggs:执行聚合。聚合语法如下

"aggs": {
	"aggs_name 这次聚合的名字,方便展示在结果集中": {
		"AGG_TYPE 聚合的类型(avg,term,terms)": {}
	}
},

在这里插入图片描述

复杂:

按照年龄聚合,并且请求这些年龄段的这些人的平均薪资

GET bank/account/_search
{
    "query":{
        "match_all":{

        }
    },
    "aggs":{
        "age_avg":{
            "terms":{
                "field":"age",
                "size":1000
            },
            "aggs":{
                "banlances_avg":{
                    "avg":{
                        "field":"balance"
                    }
                }
            }
        }
    },
    "size":1000
}

在这里插入图片描述

复杂

查出所有年龄分布,并且这些年龄段中 M 的平均薪资和 F 的平均薪资以及这个年龄段的总体平均薪资

GET bank/account/_search
{
    "query":{
        "match_all":{

        }
    },
    "aggs":{
        "age_agg":{
            "terms":{
                "field":"age",
                "size":100
            },
            "aggs":{
                "gender_agg":{
                    "terms":{
                        "field":"gender.keyword",
                        "size":100
                    },
                    "aggs":{
                        "balance_avg":{
                            "avg":{
                                "field":"balance"
                            }
                        }
                    }
                },
                "balance_avg":{
                    "avg":{
                        "field":"balance"
                    }
                }
            }
        }
    },
    "size":1000
}

在这里插入图片描述

五、Mapping

Mapping(映射)

Mapping 是用来定义一个文档(document),以及它所包含的属性(field)是如何存储和索引的。比如,使用 mapping 来定义:

1、新版本改变

Es7 及以上移除了 type 的概念。

关系型数据库中两个数据表示是独立的,即使他们里面有相同名称的列也不影响使用, 但ES 中不是这样的。elasticsearch 是基于 Lucene 开发的搜索引擎,而 ES 中不同 type 下名称相同的 filed 最终在 Lucene 中的处理方式是一样的。
    两个不同 type 下的两个user_name,在 ES 同一个索引下其实被认为是同一个 filed, 你必须在两个不同的 type 中定义相同的 filed 映射。否则,不同 type 中的相同字段名称就会在处理中出现冲突的情况,导致 Lucene 处理效率下降。
    去掉 type 就是为了提高 ES 处理数据的效率。

Elasticsearch 7.x

URL 中的 type 参数为可选。比如,索引一个文档不再要求提供文档类型。

Elasticsearch 8.x

不再支持 URL 中的 type 参数。

解决:
    将索引从多类型迁移到单类型,每种类型文档一个独立索引
    将已存在的索引下的类型数据,全部迁移到指定位置即可。详见数据迁移

创建映射

创建索引并指定映射

PUT /my-index
{
    "mappings":{
        "properties":{
            "age":{
                "type":"integer"
            },
            "email":{
                "type":"keyword"
            },
            "name":{
                "type":"text"
            }
        }
    }
}

在这里插入图片描述

添加新的字段映射

index控制字段是否被检索到

PUT /my-index/_mapping
{
    "properties":{
        "employee-id":{
            "type":"keyword",
            "index":false
        }
    }
}

在这里插入图片描述

更新映射

对于已经存在的映射字段,我们不能更新。更新必须创建新的索引进行数据迁移。

数据迁移

先创建出 new_twitter 的正确映射。然后使用如下方式进行数据迁移

POST _reindex   [固定写法]
{
    "source":{
        "index":"twitter"
    },
    "dest":{
        "index":"new_twitter"
    }
}
将旧索引的type下的数据进行迁移

POST _reindex
{
    "source":{
        "index":"twitter",
        "type":"tweet"
    },
    "dest":{
        "index":"tweets"
    }
}
转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/295116.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号