当前位置:   article > 正文

ElasticSearch-全文检索_es全局搜索

es全局搜索

一、基本概念
    1、Index(索引):名词,相当于 MySQL 中的 Database
    2、Type(类型):类似于 MySQL 中的 Table;每一种类型的数据放在一起
    3、Document(文档):文档是 JSON 格式的,Document 就像是 MySQL 中的某个 Table 里面的内容;
    4、倒排索引机制
二、Docker 安装 Es
    1、下载镜像文件
    docker pull elasticsearch:7.4.2 存储和检索数据
          docker pull kibana:7.4.2 可视化检索数
          docker   images  :查看已经安装镜像
      free -m  :查看内存
    2、创建实例
    1)、ElasticSearch
        mkdir -p /mydata/elasticsearch/config
        mkdir -p /mydata/elasticsearch/data
        echo "http.host: 0.0.0.0" >> /mydata/elasticsearch/config/elasticsearch.yml

         cat elasticsearch.yml  :查看内容

        chmod -R 777 /mydata/elasticsearch/  保证权限

         docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
        -e "discovery.type=single-node" \
        -e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
        -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.4.2

      然后就在9200端口启动了,URL输入http://192.168.56.10:9200 
    重启操作:   docker ps -a  ;查看(包括未启动的)
                         docker start 18a
    开机自启动:docker update 18a(id号) --restart=always
    删除操作:docker stop 18a;
                      docker rm 18a;
                      docker ps -a   

    2)、Kibana
    docker run --name kibana -e ELASTICSEARCH_HOSTS=http://192.168.56.10:9200 -p 5601:5601 -d kibana:7.4.2
     开机自启动:docker update 455(id号) --restart=always

三、初步检索
1、_cat
GET /_cat/nodes:查看所有节点
GET /_cat/health:查看 es 健康状况
GET /_cat/master:查看主节点
GET /_cat/indices:查看所有索引 相当于show databases;
2、索引一个文档(保存一条记录)
   保存一个数据,保存在哪个索引的哪个类型下,指定用哪个唯一标识
   http://192.168.56.10:9200/customer/external/1     :;在 customer 索引下的 external 类型下保存 1 号数据为
  put请求:{ "name": "John Doe"}

PUT 和 POST保存更新 都可以,
POST 新增。如果不指定 id,会自动生成 id。指定 id 就会修改这个数据,并新增版本号
PUT 可以新增可以修改。PUT 必须指定 id;由于 PUT 需要指定 id,我们一般都用来做修改操作,不指定 id 会报错。

 3、查询文档
    GET customer/external/1        

    更新请求:http://192.168.56.10:9200/customer/external/1?if_seq_no=2&if_primary_term=1   乐观锁机制
4、更新文档
方式一:
POST customer/external/1/_update
{ "doc":{ "name": "John Doew"
}
}
方式二:
POST customer/external/1
{ "name": "John Doe2"
}
方式三:
PUT customer/external/1
{ "name": "John Doe"
}
POST和PUT不带_updata得不对比原先数据,带_updata得对比原先数据,相同就不会有任何操作
5、删除文档&索引
    1、DELETE customer/extern  删除文档
    2、DELETE custome   删除索引
6、bulk 批量 API

https://github.com/elastic/elasticsearch/blob/7.4/docs/src/test/resources/accounts.json?raw=true 导入测试数据
    POST bank/account/_bulk
    测试数据

四、进阶检索

手册官网:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html
1、SearchAPI

ES 支持两种基本方式检索 :
⭐一个是通过使用 REST request URI 发送搜索参数(uri+检索参数)
⭐另一个是通过使用 REST request body 来发送它们(uri+请求体)
第一种方式:一切检索从_search 开始  :GET bank/_search?q=*&sort=account_number:asc
第二种方式: uri+请求体进行检索:
 

  1. GET bank/_search
  2. {
  3.   "query": {
  4.     "match_all": {}
  5.   },
  6.   "sort": [
  7.     {
  8.       "account_number": {
  9.         "order": "desc"
  10.       }
  11.     }
  12.   ]
  13. }

2、Query DSL
1)、基本语法格式
2)、返回部分字段:  "_source": ["age","balance"]

  1. GET bank/_search
  2. {
  3.   "query": {
  4.     "match_all": {}
  5.   },
  6.   "sort": [
  7.     {
  8.       "balance": {
  9.         "order": "desc"
  10.       }
  11.     }
  12.   ],
  13.   "from":0
  14.   , "size": 5,
  15.   "_source": ["age","balance"]
  16. }


3)、match【匹配查询】  全文检索
⭐ 基本类型(非字符串),精确匹配
⭐ 字符串,全文检索
⭐字符串,多个单词(分词+全文检索)

  1. GET bank/_search
  2. {
  3.   "query": {
  4.     "match": {
  5.       "address": "mill road"
  6.     }
  7.   }
  8. }


##全文检索按照评分进行排序,会对检索条件分词匹配

4)、match_phrase【短语匹配】

  1. GET bank/_search
  2. {
  3.   "query": {
  4.     "match_phrase": {
  5.       "address": "mill road"
  6.     }
  7.   }
  8. }

5)、multi_match【多字段匹配】
###也会进行分词

  1. GET bank/_search
  2. {
  3.   "query": {
  4.     "multi_match": {
  5.       "query": "mill",
  6.       "fields": ["state","address"]
  7.     }
  8.   }
  9. }


6)、bool【复合查询】
⭐must:必须达到 must 列举的所有条件
⭐must_not 必须不是指定的情况
⭐should:应该达到 should 列举的条件,如果达到会增加相关文档的评分,并不会改变查询的结果。

  1. GET bank/_search
  2. {
  3.   "query": {
  4.     "bool": {
  5.       "must": [
  6.         {
  7.           "match": {"address": "mill"}
  8.         },
  9.         {
  10.           "match": {"gender": "M"}
  11.         }
  12.       ],
  13.       "should": [
  14.         {
  15.           "match": {"address": "lane"}
  16.         }
  17.       ],
  18.       "must_not": [
  19.         {
  20.           "match": {"email": "baluba.com"}
  21.         }
  22.       ]
  23.     }
  24.   }
  25. }


7)、filter【结果过滤】
并不是所有的查询都需要产生分数,特别是那些仅用于 “filtering”(过滤)的文档。不会产生查询分数
8)、term
和 match 一样。匹配某个属性的值。全文检索字段用 match,其他非 text 字段匹配用 term
 

  1. GET bank/_search
  2. {
  3.   "query": {
  4.     "bool": {
  5.       "must": [
  6.         {
  7.           "term": {"age": {"value": "28"}}
  8.         },
  9.         {
  10.           "match": {"address": "990 Mill Road"}
  11.         }
  12.       ]
  13.     }
  14.   }
  15. }

9)、aggregations(执行聚合)
##复杂:查出所有年龄分布,并且这些年龄段中 M 的平均薪资和 F 的平均薪资以及这个年龄段的总体平均薪资

  1. GET bank/account/_sea
  2. GET bank/_search
  3. {
  4.   "query": {
  5.     "match_all": {}
  6.   },
  7.   "aggs": {
  8.     "avg_age": {
  9.       "terms": {
  10.         "field": "age",
  11.         "size": 10
  12.       },
  13.       "aggs": {
  14.         "male": {
  15.           "terms": {
  16.             "field": "gender.keyword",
  17.             "size": 10
  18.           },
  19.           "aggs": {
  20.             "avg_bal": {
  21.               "avg": {"field": "balance"}
  22.             }
  23.           }
  24.         },
  25.         "balance_avg":{
  26.           "avg": {
  27.             "field": "balance"
  28.           }
  29.         }
  30.       }
  31.     }
  32.   }
  33. }


3、Mapping 映射
手册官网:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html
GET bank/_mapping  :查询bank索引下的属性映射
1)、创建映射
 

  1. PUT /my-index
  2. {
  3.   "mappings": {
  4.     "properties": {
  5.       "age": {
  6.         "type": "integer"
  7.       },
  8.       "email": {
  9.         "type": "keyword"    //创建的是一个精确索引
  10.       },
  11.       "name": {
  12.         "type": "text"            //创建的是一个全局索引
  13.       }
  14.     }
  15.   }
  16. }

2)、添加新的字段映射

  1. PUT /my-index/_mapping
  2. {
  3.   "properties": {
  4.     "employee-id": {
  5.       "type": "keyword",
  6.       "index": false
  7.     }
  8.   }
  9. }


3)、更新映射
对于已经存在的映射字段,我们不能更新。更新必须创建新的索引进行数据迁移
4)、数据迁移
先创建出 new_twitter 的正确映射。然后使用如下方式进行数据迁移

  1. POST _reindex
  2. {
  3.   "source": {
  4.     "index": "twitter"
  5.     "type": "tweet         #当老版本中有类型,故还要加上这一行
  6.   },
  7.   "dest": {
  8.     "index": "new_twitter"
  9.   }
  10. }

4、

1)分词--安装ik分词器
将elasticsearch-analysis-ik-5.6.11.zip  解压之后放在/mydata/elasticsearch/plugins下

⭐⭐⭐一个遇到的问题,就是在plugins放入解压后的ik之后再重启elasticsearch之后,elasticsearch一直不断重启,问题解决的方案是elasticsearch
版本要和ik版本一致,我的都是7.4.2

补充:
使用MobaXterm,可以实现windos和linux的文件互传,
chmod -R 777 ik/   改变文件夹 ik/ 的权限为可读可写可执行
docker exec -it 18a /bin/bash  :进入docker中的18a项目中
exit;  退出docker
docker restart elasticsearch :   重启elasticsearch

⭐修改linux网络配置:
1、cd /etc/sysconfig/network-scripts/
2、ls
3、 ip addr 查看我们使用的是哪个网络
4、vi ifcfg-eth1
添加:
GATEWAY=192.168.56.1
DNS1=114.114.114.114
DNS2=8.8.8.8
5、重启网络 :service network restart    
6、ping baidu.com


curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo

更改Linux yum源:
更改方法:
1、进入yum配置文件目录
cd /etc/yum.repos.d/
2、备份配置文件
mv CentOS-Base.repo CentOS-Base.repo.bak
3、下载163的配置,并改名
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo
4、生成缓存
yum makecach

2)分词--安装ik分词器
POST _analyze
{
  "analyzer": "ik_smart",
  "text": "我是中国山东人"
}

安装 nginx:
1、docker下载nginx: docker run -p 80:80 --name nginx -d nginx:1.10
2、在mydata\下创建 nginx文件夹
3、将docker容器内的 nginx文件夹放到mydata下:docker container cp nginx:/etc/nginx  .
4、停止并移除docker里面的nginx:
docker stop nginx
docker rm nginx
5、在mydata下创建conf文件夹,将nginx文件目录里面的文件放到conf下,然后清空nginx,然后将conf放到nginx里面
6、创建新的nginx
docker run -p 80:80 --name nginx \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx \
-v /mydata/nginx/conf:/etc/nginx \
-d nginx:1.10
7、cd /mydata/nginx/html
8、vi index.html

输入i进入插入模式:  
<h1>Guilimall</h1>
9、在/mydata/nginx/html 下mkdir es
10、cd /mydata/nginx/html/es
       vi fenci.txt 
      加入自定义分词如:尚硅谷
10、游览器输入:http://192.168.56.10/es/fenci.txt
       就可以看到效果了,之后有想加入的自定义词汇就可以加到fenci.txt文件下
11、cd /mydata/elasticsearch/plugins/ik/config
12、vi IKAnalyzer.cfg.xml
加入:
<!--用户可以在这里配置远程扩展字典 -->
        <entry key="remote_ext_dict">http://192.168.56.10/es/fenci.txt</entry>
13、docker restart elasticsearch
14、
POST _analyze
{
  "analyzer": "ik_max_word",
  "text": "尚硅谷机构"
}

附录:

SpringBoot 整合elasticSearch:
1、创建一个springboot项目,版本为<version>2.1.8.RELEASE</version>,导入spring-web依赖和common依赖
2、导入es的rest-high-level-client

  1. <dependency>
  2. <groupId>org.elasticsearch.client</groupId>
  3. <artifactId>elasticsearch-rest-high-level-client</artifactId>
  4. <version>7.4.2</version>
  5. </dependency>

这个版本要和使用的elasticsearch版本对应,springboot默认给添加了elasticsearch版本,这时候需要添加

  1. <properties>
  2.         <java.version>1.8</java.version>
  3.         <elasticsearch.version>7.4.2</elasticsearch.version>
  4.  </properties>


3、因为导入的common依赖中包括一些数据库的依赖,此时启动文件GulimallSearchApplication需要排除数据库

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)

4、开启nacos注册中心,将该模块注册进入nacos注册中心

在application.properties中写入:
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.application.name=gulimall-search
并开启@EnableDiscoveryClient  注册发现

5、编写配置,给容器中注入一个RestHighLevelClient

  1. @Configuration
  2. public class GulimallElasticSearchConfig {
  3.     @Bean
  4.     public RestHighLevelClient esRestClient(){
  5.        RestClientBuilder builder =null;
  6.        builder = RestClient.builder(new HttpHost("192.168.56.10", 9200, "http"));
  7.        RestHighLevelClient client = new RestHighLevelClient(builder);
  8.        return client;
  9.     }
  10. }

java测试篇:
一:测试容器中是否已经注入了RestHighLevelClient
 

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class GulimallSearchApplicationTests {
  4.     @Autowired
  5.     private RestHighLevelClient client;
  6.     @Test
  7.     public void contextLoads() {
  8.         System.out.println(client);
  9.     }
  10. }


二、测试存储、更新ES数据
参考文档API:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-document-index.html
   

  1. @Test
  2.     public void indexData() throws IOException {
  3.         //创建索引
  4.         IndexRequest indexRequest = new IndexRequest("users");
  5.         //数据的id
  6.         indexRequest.id("1");
  7.         User user = new User();
  8.         user.setUserName("zhangsan");
  9.         user.setAge(18);
  10.         user.setGender("男");
  11.         String jsonString = JSON.toJSONString(user);
  12.         indexRequest.source(jsonString, XContentType.JSON);
  13.         //执行索引保存操作
  14.         IndexResponse index = client.index(indexRequest, GulimallElasticSearchConfig.COMMON_OPTIONS);
  15.         //提取有用的响应数据
  16.         System.out.println(index);
  17.     }
  18.     @Data
  19.     class User {
  20.         private String userName;
  21.         private String gender;
  22.         private Integer age;
  23.     }


三、复杂检索:在bank中搜索address中包含mill的所有人的年龄分布以及平均年龄,平均薪资
参考文档API:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-search.html
利用在线软件将json生成java实体类:https://www.bejson.com/json2javapojo/new/
   

  1. @ToString
  2.     @Data
  3.     static class Account {
  4.         private int account_number;
  5.         private int balance;
  6.         private String firstname;
  7.         private String lastname;
  8.         private int age;
  9.         private String gender;
  10.         private String address;
  11.         private String employer;
  12.         private String email;
  13.         private String city;
  14.         private String state;
  15.     }
  16.     @Test
  17.     public void searchData() throws IOException {
  18.         //1. 创建检索请求
  19.         SearchRequest searchRequest = new SearchRequest();
  20.         //1.1)指定索引
  21.         searchRequest.indices("bank");
  22.         //1.2)构造检索条件
  23.         SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
  24.         sourceBuilder.query(QueryBuilders.matchQuery("address", "Mill"));
  25. //        System.out.println("检索条件:"+sourceBuilder.toString());
  26.         
  27.         //1.2.1)按照年龄分布进行聚合
  28.         TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg").field("age").size(10);
  29.         sourceBuilder.aggregation(ageAgg);
  30.         //1.2.2)计算平均年龄
  31.         AvgAggregationBuilder ageAvg = AggregationBuilders.avg("ageAvg").field("age");
  32.         sourceBuilder.aggregation(ageAvg);
  33.         //1.2.3)计算平均薪资
  34.         AvgAggregationBuilder balanceAvg = AggregationBuilders.avg("balanceAvg").field("balance");
  35.         sourceBuilder.aggregation(balanceAvg);
  36. //        System.out.println("检索条件:" + sourceBuilder.toString());
  37.         searchRequest.source(sourceBuilder);
  38.         //2. 执行检索
  39. //        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
  40.         SearchResponse searchResponse = client.search(searchRequest, GulimallElasticSearchConfig.COMMON_OPTIONS);
  41.         System.out.println("检索结果:" + searchResponse.toString());
  42.         
  43.         //3. 将检索结果封装为Bean
  44.         //得到第一层的hits
  45.         SearchHits hits = searchResponse.getHits();
  46.         //得到第二层的hits
  47.         SearchHit[] searchHits = hits.getHits();
  48.         for (SearchHit searchHit : searchHits) {
  49.             String sourceAsString = searchHit.getSourceAsString();
  50.             Account account = JSON.parseObject(sourceAsString, Account.class);
  51.             System.out.println(account);
  52.         }
  53. //        //4. 获取聚合信息
  54.         Aggregations aggregations = searchResponse.getAggregations();
  55.         Terms ageAgg1 = aggregations.get("ageAgg");
  56.         for (Terms.Bucket bucket : ageAgg1.getBuckets()) {
  57.             String keyAsString = bucket.getKeyAsString();
  58.             System.out.println("年龄:" + keyAsString + " ==> " + bucket.getDocCount());
  59.         }
  60.         Avg balanceAvg1 = aggregations.get("balanceAvg");
  61.         System.out.println("平均薪资:" + balanceAvg1.getValue());
  62.     }
  63.      


        

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/305762
推荐阅读
相关标签
  

闽ICP备14008679号