1、官网下载,安装方式多样,这里选择docker
docker pull docker.elastic.co/elasticsearch/elasticsearch:7.14.0
2、创建普通用户以便于使用Elasticsearch
- # root用户可以使用docker,普通用户无法使用,是因为没有权限。
- # 查看当前用户
- whoami
- # 创建新用户
- adduser username
- # 设置用户密码
- passwd username
- # 创建一个新的docker组
- groupadd docker
- # 添加新用户到docker组
- usermod -a -G docker username
- # 更新docker组
- newgrp docker
- # 修改docker.sock权限为root用户docker组
- chown root:docker /var/run/docker.sock
- # 切换到新用户
- su username
3、创建Elasticsearch容器
- docker run
- --name elasticsearch # 容器名称
- -p 9200:9200 # 映射端口 接受http协议
- -p 9300:9300 # 接受TCP协议
- -e "discovery.type=single-node" # 单节点式
- -e ES_JAVA_OPTS="-Xms84m -Xmx512m" # 内存大小
- -v /home/docker/elasticsearch/data:/usr/share/elasticsearch/data # 挂载目录
- -v /home/docker/elasticsearch/logs:/usr/share/elasticsearch/logs
- -v /home/docker/elasticsearch/plugins:/usr/share/elasticsearch/plugins
- -d
- elasticsearch:8.7.0
4、Kibana安装,安装方式多样,这里也选择docker
- # 拉取镜像
- docker pull kibana:7.14.0
- # 挂载数据卷,创建容器
- docker run -d
- --name kibana
- -p 5601:5601
- -v /home/es/kibana/kibana.yml:/usr/share/kibana/config/kibana.yml
- 58dffcbc8caa
5、拷贝容器内的文件
docker cp <containerId>:/path/to/file /path/on/host
6、索引操作
- # 查询全部索引
- GET /_cat/indices?v
- # 创建索引
- PUT /indexName
- # 创建一个索引并使用json格式传参,设置主分片为1副本分片数量为零
- PUT /indexName
- {
- "settings": {
- "number_of_shards": 1
- , "number_of_replicas": 0
- }
- }
- # 删除一个索引
- DELETE /indexName
- # 删除所有索引
- DELETE /*
7、映射操作
字符串类型:keyword、text
整数类型:integer、long
小数类型:float、double
布尔类型:boolean
日期类型:date
- # 创建索引时创建映射
- PUT /indexName
- {
- "settings": {
- "number_of_shards": 1
- , "number_of_replicas": 0
- }
- , "mappings": {
- "properties": {
- "id":{
- "type": "integer"
- },
- "title":{
- "type": "keyword"
- },
- "price":{
- "type": "double"
- },
- "update_time":{
- "type": "date"
- },
- "describe":{
- "type": "text"
- }
- }
- }
- }
- # 查看索引的映射
- GET /indexName/_mapping
8、文档操作
- # 根据映射向索引中创建一条文档,自动指定id
- POST /indexName/_doc
- {
- "title":"电冰箱",
- "price":2.99,
- "update_time":"2023-03-25",
- "describe":"很好用"
- }
- # 手动指定id
- POST /indexName/_doc/id
- {
- "title":"电冰箱",
- "price":2.99,
- "update_time":"2023-03-25",
- "describe":"很好用"
- }
- # 根据文档id查询文档
- GET /indexName/_doc/id
- # 根据id删除文档
- DELETE /indexName/_doc/id
- # 根据id更新文档,先删除再更新,覆盖式更新
- PUT /indexName/_doc/id
- {
- "title":"电视机"
- }
- # 根据id更新文档,只覆盖更新部分
- POST /indexName/_doc/id/_update
- {
- "doc" : {
- "title":"电视据"
- }
- }
- # 批量操作文档,指定id同时插入两条数据
- POST /indexName/_doc/_bulk
- {"index":{"_id":7}}
- {"title":"瓜子","price":3.99,"update_time":"2022-04-23","describe":"好吃"}
- {"index":{"_id":8}}
- {"title":"饮料","price":4.99,"update_time":"2020-04-22","describe":"好喝"}
- # 批量操作文档,指定id插入更新删除
- POST /indexName/_doc/_bulk
- {"index":{"_id":9}}
- {"title":"矿泉水","price":8.99,"update_time":"1921-09-23","describe":"矿泉水也好喝"}
- {"update":{"_id":9}}
- {"doc":{"describe":"矿泉水好喝是好喝,就是太贵啦"}}
- {"delete":{"_id":1}}
-
-
-
-
-
9、高级文档查询
- # 查询索引中的所有文档
- GET /indexName/_doc/_search # 或使用GET /indexName/_search
- {
- "query":{
- "match_all":{}
- }
- }
- # 根据索引中的关键词查询
- # keyword类型、Integer类型、double类型、date类型、boolean类型、float类型、long类型不分词
- # text类型,es会使用分词器进行分词,中文单字查询英文单个单词(空格)查询
- GET /indexName/_doc/_search
- {
- "query":{
- "term":{ # term代表关键词查询
- "price":3.99
- }
- }
- }
- # 范围查询
- GET /indexName/_doc/_search
- {
- "query":{
- "range":{ # range代表范围查询
- "price":{
- "gte":2, # gte大于等于、gt大于
- "lte":3 # lte小于等于、lt小于
- }
- }
- }
- }
- # 前缀查询,查询指定前缀的内容
- GET /indexName/_doc/_search
- {
- "query":{
- "prefix":{ # prefix代表前缀查询
- "title":"瓜"
- }
- }
- }
- # 通配符查询,"?"代表任意一个字符,"*"代表任意多个字符
- GET /indexName/_doc/_search
- {
- "query":{
- "wildcard":{ # wildcard代表通配符查询
- "title":"?泉*"
- }
- }
- }
- # 多id查询
- GET /indexName/_doc/_search
- {
- "query":{
- "ids":{
- "values":["7","8","9"]
- }
- }
- }
- # 模糊查询。搜索关键词长度为2不允许出现模糊、关键词长度为3-5允许一次模糊、关键词长度大于五允许两次模糊
- GET /indexName/_doc/_search
- {
- "query":{
- "fuzzy":{
- "title":"矿石水" # 文档中为矿泉水
- }
- }
- }
- # 布尔查询。关键字must等价于&&、should等价于||、must_not相当于!
- GET /indexName/_doc/_search
- {
- "query":{
- "bool":{
- "must":[{
- "ids":{
- "values":[7,8,9]
- }
- }]
- }
- }
- }
- # 多字段查找某个值,只能在同一类型(字符串或数字)的字段中查找,如果给出的字段类型不同会报错
- # 如果查找的类型为字符串,会进行分词分别查找
- GET /indexName/_doc/_search
- {
- "query": {
- "multi_match": {
- "query": "饮料",
- "fields": ["title","describe"]
- }
- }
- }
- # 默认字段查询,默认字段分词就分词查询,默认字段不分词就不分词查询
- GET /indexName/_doc/_search
- {
- "query":{
- "query_string":{
- "default_field":"describe",
- "query":"好喝"
- }
- }
- }
10、文档查询其他操作
- # 高亮查询结果
- GET /indexName/_doc/_search
- {
- "query":{
- "query_string":{
- "default_field":"describe",
- "query":"好喝"
- }
- },
- "highlight":{ # 高亮关键词
- "fields":{
- "*":{}
- }
- }
- }
- # 控制显示文档条数
- GET /indexName/_doc/_search
- {
- "query":{
- "match_all":{}
- },
- "size":3 # 文档条数关键词
- }
- # 选择查询的起始位置,从零开始
- GET /indexName/_doc/_search
- {
- "query":{
- "match_all":{}
- },
- "from":0
- }
- # 对查询结果进行排序
- GET /indexName/_doc/_search
- {
- "query":{
- "match_all":{}
- },
- "sort":{ # 排序关键词
- "price":{
- "order":"desc" # 选择降序
- }
- }
- }
- # 查询指定字段
- GET /indexName/_doc/_search
- {
- "query":{
- "match_all":{}
- },
- "_source":["title","describe"] # 指定需要查询的字段
- }
11、ES索引规则:倒排索引
ES存储区:索引区、元数据区
倒排索引:把文档存在元数据区,将文档中不同类别和分词的数据分别与文档id绑定存在索引区,查询时,根据索引区数据找到对应元数据区的文档。
12、ES默认标准分词器
结构:字符过滤器(进行预处理例如过滤html标签)、分词器、Token过滤器(加工分好的词)
内置分词器:
①标准分词器Standard:英文按单词切分,中文按字切分,过滤符号,并小写处理
②简单分词器Simple:英文按单词切分中文按空格切分,过滤符号,小写处理
③停用词过滤分词器Stop:小写处理,停用this、a、an等词的过滤
④Whitespace:按空格切分,不过滤符号,不小写处理
⑤Keyword:不分词
- # standard
- POST /_analyze
- {
- "analyzer": "standard"
- , "text": ["i am a good boy"]
- }
- # simple
- POST /_analyze
- {
- "analyzer": "simple"
- , "text": ["i am a good boy,这里是中文"]
- }
- # whitespace
- POST /_analyze
- {
- "analyzer": "whitespace"
- , "text": ["I am a good boy,这里是中文"]
- }
- # 创建映射时手动指定字段的分词器,只能指定可以分词的类型
- PUT /user
- {
- "settings": {
- "number_of_shards": 1
- , "number_of_replicas": 0
- },
- "mappings": {
- "properties": {
- "title":{
- "type": "text"
- , "analyzer": "standard"
- }
- }
- }
- }
13、中文分词器IK
- # 分词器版本与ES版本一致
- # 下载分词器https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.14.0/elasticsearch-analysis-ik-7.14.0.zip
- # 解压至es容器中plugins目录
- # 粗粒度分词器
- POST /_analyze
- {
- "analyzer": "ik_smart"
- ,"text": ["这里是中文"]
- }
- # 细粒度分词器
- POST /_analyze
- {
- "analyzer": "ik_max_word"
- ,"text": ["这里是中文"]
- }
14、扩展词:将非关键词的词加入词典
停用词:将关键词移除词典
- # IK设置扩展词典和停用词典
- # 在ik/config/IKAnalyzer.cfg.xml文件中设置停用词典文件和扩展词典文件
- # 两个文件与IKAnalyzer.cfg.xml放在同一目录中,文件中每一行设置一个关键词
15、过滤查询
- # 必须包裹在布尔查询内,与布尔查询连用,有filter关键字省略query关键字
- # 先执行filter再执行布尔
- GET /product/_doc/_search
- {
- "query":{
- "bool":{
- "must":[{
- "range":{
- "price":{
- "lte":10
- ,"gte":0
- }
- }
- }],
- "filter":{
- "wildcard":{
- "describe":"*喝*"
- }
- }
- }
- }
- }
16、ES整合SpringBoot
- # 依赖
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
- </dependency>
- # 配置
- @Configuration
- public class ESConfig extends AbstractElasticsearchConfiguration {
-
- @Value("${url}")
- String url;
- @Override
- @Bean
- public RestHighLevelClient elasticsearchClient() {
- final ClientConfiguration clientConfiguration = ClientConfiguration.builder().connectedTo(url).build();
- return RestClients.create(clientConfiguration).rest();
- }
- }
17、两种操作ES方式:
ElasticserachOperations 面向对象
RestHighLevelClient restful风格、封装了ES细节
18、ElasticserachOperations方式
- //实体类创建索引
- @Document(indexName = "product",createIndex = true) //索引名,是否创建索引
- public class Product {
-
- @Id //将id与文档_id进行映射
- private Integer id;
-
- @Field(type = FieldType.Keyword) //主要是指定字段类型
- private String title;
-
- @Field(type = FieldType.Double)
- private Double price;
-
- @Field(type = FieldType.Text)
- private String describe;
-
- }
- //创建索引并插入文档对象
- @SpringBootTest //测试类注解该加还得加,不然无法注入
- public class Test {
-
-
- @Autowired
- ElasticsearchOperations elasticsearchOperations;
-
- @org.junit.jupiter.api.Test
- public void create(){
- Product product = new Product();
- product.setId(1);
- product.setTitle("上周青花瓷");
- product.setPrice(3.99);
- product.setDescribe("的确是上周的青花瓷,还带着烟火香");
- elasticsearchOperations.save(product); //文档对象存入es,id不存在添加,id存在更新
-
-
- }
- }
- //根据id查询文档对象
- @org.junit.jupiter.api.Test
- public void get(){
-
- Product product = elasticsearchOperations.get("1",Product.class);
- System.out.println(product.toString());
- }
- //删除全部文档
- @org.junit.jupiter.api.Test
- public void deleteAll(){
- elasticsearchOperations.delete(Query.findAll(), Product.class);
- }
- //查询全部文档
- @org.junit.jupiter.api.Test
- public void find() throws JsonProcessingException {
- SearchHits<Product> searchHits = elasticsearchOperations.search(Query.findAll(), Product.class);
- for (SearchHit<Product> s :searchHits){
- System.out.println(new ObjectMapper().writeValueAsString(s.getContent()));
- }
- }
-
-
-
19、RestHighLevelClient方式
创建索引
- //使用Query DSL语法,创建索引
- @Test
- public void creat() throws IOException {
- CreateIndexRequest createIndexRequest = new CreateIndexRequest("product"); //创建索引名
- createIndexRequest.settings("{\n" + //设置分片
- " \"number_of_shards\": 1\n" +
- " , \"number_of_replicas\": 0\n" +
- " }",XContentType.JSON);
- createIndexRequest.mapping("{\n" + //设置映射
- " \"properties\": {\n" +
- " \"id\":{\n" +
- " \"type\": \"integer\" \n" +
- " },\n" +
- " \"title\":{\n" +
- " \"type\": \"keyword\"\n" +
- " },\n" +
- " \"price\":{\n" +
- " \"type\": \"double\"\n" +
- " },\n" +
- " \"update_time\":{\n" +
- " \"type\": \"date\"\n" +
- " },\n" +
- " \"describe\":{\n" +
- " \"type\": \"text\"\n" +
- " , \"analyzer\": \"ik_max_word\"\n" +
- " }\n" +
- " }}", XContentType.JSON);
- CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
- restHighLevelClient.close();
- }
删除索引
- @Test
- public void delet() throws IOException {
-
- DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("product");
- restHighLevelClient.indices().delete(deleteIndexRequest,RequestOptions.DEFAULT);
- restHighLevelClient.close();
-
- }
向指定索引中增加数据
- @Test
- public void add() throws IOException {
-
- IndexRequest indexRequest = new IndexRequest("product"); //指定索引
- indexRequest.id("1"); //指定id、可以不指定自动分配
- indexRequest.source("{\n" + //指定数据
- " \"title\":\"电冰箱\",\n" +
- " \"price\":2.99,\n" +
- " \"update_time\":\"2023-03-25\",\n" +
- " \"describe\":\"很好用\"\n" +
- "}",XContentType.JSON);
- restHighLevelClient.index(indexRequest,RequestOptions.DEFAULT);
- restHighLevelClient.close();
- }
更新文档
- @Test
- public void update() throws IOException {
-
- UpdateRequest updateRequest = new UpdateRequest("product","1");
- updateRequest.doc("{\n" +
- " \"title\":\"电视据\"\n" +
- " }",XContentType.JSON);
- restHighLevelClient.update(updateRequest,RequestOptions.DEFAULT);
- restHighLevelClient.close();
- }
删除文档
- @Test
- public void dele() throws IOException {
-
- DeleteRequest deleteRequest = new DeleteRequest("product");
- deleteRequest.id("1");
- restHighLevelClient.delete(deleteRequest,RequestOptions.DEFAULT);
- restHighLevelClient.close();
- }
基于id查询文档
- @Test
- public void gett() throws IOException {
-
- GetRequest getRequest = new GetRequest("product");
- getRequest.id("1");
- GetResponse getResponse = restHighLevelClient.get(getRequest,RequestOptions.DEFAULT);
- String s = getResponse.toString();
- System.out.println(s);
- restHighLevelClient.close();
- }
查询所有
- @Test
- public void getAll() throws IOException {
- SearchRequest searchRequest = new SearchRequest("product");
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- searchSourceBuilder.query(QueryBuilders.matchAllQuery());
- searchRequest.source(searchSourceBuilder);
- //searchResponse结果就是kibana中查询返回结果
- SearchResponse searchResponse = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
- String s = searchResponse.toString();
- System.out.println(s);
- }
按条件查询
- @Test
- public void quer() throws IOException {
- SearchRequest searchRequest = new SearchRequest("product");
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- searchSourceBuilder.query(QueryBuilders.termQuery("describe","好用"));
- searchRequest.source(searchSourceBuilder);
- SearchResponse searchResponse = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
- String s = searchResponse.toString();
- System.out.println(s);
-
- }
分页查询,指定从第二条开始查询,总计查询一条
- @Test
- public void sort() throws IOException {
- SearchRequest searchRequest = new SearchRequest("product");
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- searchSourceBuilder.query(QueryBuilders.matchAllQuery()).from(1).size(1);
- searchRequest.source(searchSourceBuilder);
- SearchResponse s = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
- System.out.println(s.toString());
- }
降序查询
- @Test
- public void sort() throws IOException {
- SearchRequest searchRequest = new SearchRequest("product");
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- searchSourceBuilder.query(QueryBuilders.matchAllQuery()).from(0).size(10).sort("price",SortOrder.DESC);
- searchRequest.source(searchSourceBuilder);
- SearchResponse s = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
- System.out.println(s.toString());
- }
返回指定的字段,排除describe,接受title、price
- @Test
- public void sort() throws IOException {
- SearchRequest searchRequest = new SearchRequest("product");
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- searchSourceBuilder.query(QueryBuilders.matchAllQuery()).from(0).size(10).sort("price",SortOrder.DESC).fetchSource(new String[]{"price","title"},new String[]{"describe"});
- searchRequest.source(searchSourceBuilder);
- SearchResponse s = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
- System.out.println(s.toString());
- }
使用HighLightBuilder对查询结果进行高亮显示
- @Test
- public void quer() throws IOException {
- SearchRequest searchRequest = new SearchRequest("product");
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- HighlightBuilder highlightBuilder = new HighlightBuilder();
- highlightBuilder.requireFieldMatch(false).field("describe").field("title");
- searchSourceBuilder.query(QueryBuilders.termQuery("describe","好喝")).highlighter(highlightBuilder);
- searchRequest.source(searchSourceBuilder);
- SearchResponse searchResponse = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
- String s = searchResponse.toString();
- System.out.println(s);
-
- }
过滤查询
- @Test
- public void fget() throws IOException {
- SearchRequest searchRequest = new SearchRequest("product");
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
-
- searchSourceBuilder.query(QueryBuilders.matchAllQuery()).postFilter(QueryBuilders.termQuery("describe","好喝"));
- searchRequest.source(searchSourceBuilder);
- SearchResponse s =restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
- System.out.println(s);
-
-
- }
ES对象存取
- //作为对象存入
- @Test
- public void las() throws IOException {
- Product product = new Product();
- product.setId(4);
- product.setTitle("黑鱼片");
- product.setPrice(28.0);
- product.setDescribe("很好吃");
- product.setUpdate_time(new Date());
- IndexRequest indexRequest = new IndexRequest("product");
- indexRequest.id(String.valueOf(product.getId())).source(new ObjectMapper().writeValueAsString(product),XContentType.JSON);
- IndexResponse s = restHighLevelClient.index(indexRequest,RequestOptions.DEFAULT);
- System.out.println(s.isFragment());
-
-
- }
- //取出存为对象
- @Test
- public void lget() throws IOException, JSONException {
-
- SearchRequest searchRequest = new SearchRequest("product");
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- searchSourceBuilder.query(QueryBuilders.matchAllQuery());
- searchRequest.source(searchSourceBuilder);
- SearchResponse s = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
- org.elasticsearch.search.SearchHit[] searchHits = s.getHits().getHits();
- List<Product> list = new ArrayList<>();
- for (org.elasticsearch.search.SearchHit a :searchHits){
- Product product = new ObjectMapper().readValue(a.getSourceAsString(),Product.class);
- list.add(product);
- }
- for (int i =0;i<list.size();i++){
- System.out.println(list.get(i));}
- }
20、聚合查询
Query DSL
- //查某一个字段,
- GET /product/_search
- {
- "query":{
- "match_all": {}
- },
- "aggs":{
- "dd_all":{ //这里是聚合查询名,可以随便定义
- "terms": {
- "field": "price", //查询价格
- "size": 10
- }
- }
- }
- }
- //查询最大值
- GET /product/_search
- {
- "query": {
- "match_all": {}
- },
- "aggs": {
- "dd_max":{
- "max": {
- "field": "price" //查询价格最大值
- }
- }
- }
- }
- //查询最小值
- GET /product/_search
- {
- "query": {
- "match_all": {}
- },
- "aggs": {
- "dd_min":{
- "min": {
- "field": "price" //这里查询价格最小值
- }
- }
- }
- }
- //查询平均值
- GET /product/_search
- {
- "query": {
- "match_all": {}
- },
- "aggs": {
- "dd_average":{
- "avg": {
- "field": "price" //这里查询价格平均值
- }
- }
- }
- }
RestHighLevelClient
- //查询字段所有
- @Test
- public void agg() throws IOException {
- SearchRequest searchRequest = new SearchRequest("product");
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- searchSourceBuilder.query(QueryBuilders.matchAllQuery()).aggregation(AggregationBuilders.terms("price_all").field("price"));
- searchRequest.source(searchSourceBuilder);
- SearchResponse s = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
- System.out.println(s);
- }
- //查询字段最大值
- @Test
- public void aggm() throws IOException {
- SearchRequest searchRequest = new SearchRequest("product");
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- searchSourceBuilder.query(QueryBuilders.matchAllQuery()).aggregation(AggregationBuilders.max("max_all").field("price"));
- searchRequest.source(searchSourceBuilder);
- SearchResponse s = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
- System.out.println(s);
- }
- //
21、集群搭建
配置文件
- # 集群名称
- cluster.name: es_cluster
- # 节点名称
- node.name: node_1
- # 开启远程访问
- network.host: 0.0.0.0
- # 使用发布地址进行集群间通信
- network.publish_host: IP
- # http通信端口
- http.port: 9201
- # tcp通信端口
- transport.tcp.port: 9301
- # 指定节点的tcp通信
- discovery.seed_hosts: ["IP:9301","IP:9302","IP:9303"]
- # 集群初始化节点
- cluster.initial_master_nodes: ["node_1","node_2","node_3"]
- # 集群最少可用节点
- gateway.recover_after_nodes: 2
- # 开启跨域
- http.cors.enabled: true
- # 跨域请求前缀
- http.cors.allow-origin: "*"
kibana配置到es集群
- server.host: "0"
- server.shutdownTimeout: "5s"
- elasticsearch.hosts: [ "http://IP:9201","http://IP:9202","http://IP:9203" ]
- monitoring.ui.container.elasticsearch.enabled: true