# TestElasticSearch **Repository Path**: cyhgyq/test-elastic-search ## Basic Information - **Project Name**: TestElasticSearch - **Description**: 学习ElasticSearch - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-08-06 - **Last Updated**: 2022-09-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ElasticSearch 6.x 和7.x版本很大区别,学习7.x 分原生api和RestFul高级 SQL:like 方式搜索大数据很慢,即使加了索引也达不到要求 ElasticSearch: 大数据量的搜索, 搜索框架还有Solr, ElasticSearch比Solr快50倍左右 要求: jdk1.8, ElasticSearch客户端,界面工具 下载: https://www.elastic.co/cn/elasticsearch/ 很大1个多G 需要下载核心包(官网下载),analysis-ik分词器(github上下载),head-mast处理器(github上下载下面会说), kibana 可以在windows或linux下学习 ELK三剑客,elasticaSearch, Logstash,Kibana, 解压即用 解压出现文件夹就可以使用了: bin:启动文件, 双击elasticsearch.bat启动 config: 配置文件 log4j2:日志配置文件 jvm.option: java虚拟机的配置 -Xms256m 需要的内存,默认1G, 很大服务器和电脑跑步起来,改成256m -Xmx256m elasticsearch.yml: elasticsearch的配置文件,默认9200端口, 小心跨域问题 lib: jar包 modules: 功能模块 plugin: 插件,如ik分词器插件 启动后浏览器输入:127.0.0.1:9200 安装可视化界面:百度搜索:elasticsearch head 得到地址: https://github.com/mobz/elasticsearch-head/ 下载这个前端项目运行起来, 默认端口9100 浏览器输入:127.0.0.1:9100, 在界面的链接输入框中输入:http://localhost:9200, 连接失败,f12打印中出现跨域问题 在elaticsearch.yml的配置文件配置一下: http.cors.enabled: true http.cors.allow-origin: "*" 来解决跨域问题,重新连接成功了 界面里面 索引 其实表示数据库的意思 数据浏览 可以看到某个索引的所有数据 复合查询 就是一些查询json语句 head就是一个数据展示工具,不建议在里面写查询语句,因为里面语句没有格式化,应该在kibana里面写查询语句 安装Kibana: https://www.elastic.co/cn/kibana 注意下载的版本必须和上面下载的elasticSearch的版本一致 解压需要一些时间,然后双击bin文件夹中的启动文件, 里面会显示http://localhost:5601, 浏览器打开 点击界面的小扳手图标,里面就可以写各种查询语句了 汉化:config/kibana.yml i18.local: "en" 改成 zh-CN, 重启项目 集群、节点、索引、类型、文档、分片、映射是什么? elasticSearch是面向文档的,一切都是json mysql与elasticsearch对比: mysql elasticsearch 数据库 索引(indices) 表 types(已经弃用) 行 documents(文档) 字段 fields 一个人也是一个群,也会进行分片 安装ik分词器:https://github.com/medcl/elasticsearch-annlysis-ik 下载完成后,解压,在elaticsearch的plugins中建立文件夹名字ik, 将解压的内容拷贝到这个文件夹中,重启elasticsearch 在kibana的小扳手里面输入下面内容: ik_smart 智能分词, ik_max_word 最细粒度分词 GET _analyze { "analyzer": "ik_smart", "text": "中国" } GET _analyze { "analyzer": "ik_max_word", "text": "中国" } 自定义词加到ik分词器中: config下面加一个文件:my.dic, 里面输入我们的词 config/IKAnaly.cfg.yml ,配置: my.dic 重启elasticsearch, 里面可以配置新词和停止使用的词, 还有远程词典的配置,这样就不需要重启了,es会每隔一段时间从服务器拉取词典 Rest基本语法: 创建索引并插入一条数据: PUT test1/_doc/1 /索引名/_doc/文档id _doc是类型,固定用这个, 一起自定义类型功能被弃用了 { "name": "cyh", "age": 18 } 创建索引,不插入数据,但是指定字段类型,java类对应方便,字段类型不能够修改 ,如果需要改,必修新建索引,将旧的索引复制到新的索引中,有很多类型,可以在网上找 PUT test2 { "settings" : { "analysis": { "analyzer": { "ik": { "tokenizer": "ik_max_word" //添加ik分词器的设置 有ik_max_work和ik_smart两种, 这一句可以不加 } } } } "mappings": { "properties": { "name": { "type": "text", "analyzer": "ik_max_word" //表示加ik分词器, 这一句可以不加 }, "age": { "type": "long" } } } } 获取各个字段的类型 GET /test2/_mapping GET /test2/_mapping/logs GET /test2/_mapping/logs/field/age 添加字段,shez leix POST /test2/_mapping/logs { "properties": {"number": {"type": "text"}} } 设置分片数,默认5个, 只能初始化是设置,后续不能修改 PUT /test2/_settings { "number_of_replicas": 2 } 获取分片数 GET /test2/_settings 索引拷贝,可以解决字段类型变更的问题,即类似数据库拷贝 POST _reindex { "source": { "index": "test2" }, "dest": { "index": "test3" } } 测试分词 GET _analyze?pretty { "analyzer": "ik_max_word", "text": "重卡是家乐福" } 获取索引的信息: GET test2 GET _cat/ 会获得很多默认的信息 GET test1/_doc/1 GET test1/_doc/_search?q=name:cyh 搜索这个库里面符合条件的, 分词器只对text类型有作用,对keyword类型没有作用, 查询结果中_score表示匹配度,max_score最大的匹配分值 GET test1/_doc/_search 如果后加上?pretty表示格式化,使变得更好看 { "query": { "match": { //match匹配查询会使用分词器或者term倒排查询直接查找精确的值, 还可以改成range "name": "cyh" //可以用空格隔开多个词表示分别查询匹配多个值符合 } "bool" : { //bool查询, 即多条件查询 "must": [ //must表示所有条件都要符合, should表示可以满足也可以不满足这个条件,must_not表示不符合下面条件 { "match": { "name": "cyh" 如果是["cyh", "cyh2"]则表示满足这两个的一个条件就行 } }, { "match": { "age": 10 } } ], "filter": { "range": { "age": { "gte": 10, "lt": 18 //表示查出的结果过滤出年龄小于18岁的, gt gte lt lte } } } } } "_source": ["name", "age"], //过滤字段,表示只查出这几个字段 "sort": [ //查询结果的排序方式 { "age": { "order": "desc" } } ], "from": 0, //分页,从第几个数据开始, 这种方式只适用于小量数据的情况 "size": 10, //分页,查询结果几个数据, 设置1,表示只查1个数据 "highlight": { //高亮显示name匹配的结果 "pre_tags": "

", //前缀 "post_tags": "

", //后缀 "fields": { "name": {} } } } 更新数据: POST test1/_doc/1/_update //如果没有加_update, 则除了更新字段,其它字段都会删除 { "doc": { "name": "cyh2" } } 删除命令: DELETE test1/_doc/1 批量添加数据 PUT /tes2/_bulk {} 大量数据分页查询时 先得到scrollId GET test2/_search?scroll=3m { "query": {"match_all": {}}, "size": 3 } 通过scrollId查询 GET /_search/scroll { "scroll": "1m", //数据缓存时间 "scroll_id": "上一步得到的scrollId" } # springboot集成elasticSearch 在官网找Elasticsearch Clients,点击进入,里面有不同平台的集成方式,推荐java Rest 点击进去---选择Java High Level Rest Client, 选择高级的客户端, 里面有全套的文档 idea->Spring initializr->NoSql->Elasticsearch idea->Project Structure->Project->jdk1.8,版本改成8 idea->settings->java compier->改成jdk1.8, javaScript->es6 修改elasticSearch的pom版本,否则出错 7.6.1 //跟我们服务器安装的elasticsearch版本要一致 代码: @Configuration public class ElasticSearchClientConfig { @Bean public RestHighLevelClient restHighLevelClient() { RestHighLevelClient client = new RestHighLevelClient ( RestClient.builder( new HttpHost("127.0.0.1", 9200, "http") //如果集群有多个,逗号隔开填多个 ) ) return client; } } 测试文件中使用: @Autowired @Qualifier("restHighLevelClient") private RestHighLevelClient client; //创建索引 @Test void testCreateIndex() { //创建索引请求 CreateIndexRequest request = new CreateIndexRequest("cyh_index"); //执行请求, 获得响应数据 CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT); } //获取索引 @Test voie testExistIndex() { GetIndexRequest request = new GetIndexRequest("cyh_index"); boolean exists = client.indices.exists(request, RequestOptions.DEFAULT); } //删除索引 @Test void testDeleteIndex() { DeleteIndexRequest request = new DeleteIndexRequest("cyh_index"); AcknowledgeResponse delete = client.indices().delete(request, RequestOptions.DEFAULT); //delete.isAcknowledged();表示是否删除成功 } //添加文档 @Test void testAddDocument() { User user = new User("cyh", 18); IndexRequest request = new IndexRequest("cyh_index"); //设置elesticSearch的自带的东西 request.id("1"); request.timeout(TimeValue.timeValueSeconds(1)); //设置elesticSearch的文档体 request.source(JSON.toJSONString(user).XContentType.JOSN); //客户端发送请求 IndexResponse response = client.index(request, RequestOptions.DEFAULT); } //获取文档,判断文档是否存在 @Test void testIsExists() { GetRequest getRequest = new GetRequest("cyh_index", "1"); boolean exists = clients.exists(getRequsts, RequestOptions.DEFAULT); } //获取文档的信息 @Test void testGetDocument() { GetRequest getRequest = new GetRequest("cyh_index", "1"); GetResponse response = client.get(getRequest, RequestOptions.DEFAULT); //打印response 和 response.getSourceAsString() } //更新文档 @Test void testUpdateDocument() { UpdateRequest updateRequest = new UpdateRequest("cyh_index", "1"); updateRequest.timeout("1s"); User user = new User("cyh2", 18); updateRequest.doc(JSON.toJSONString(user), XContentType.JSON); UpdateResponse response = client.update(updateRequest, RequestOptions.DEFAULT); } //删除文档 @Test void testDeleteDocument() { DeleteRequest request = new DeleteRequest("cyh_index", "3"); request.timeout("1s"); DeleteResponse deleteResponse = client.delete(request, RequestOptions.DEFAULT); //通过deleteResponse.status()来判断是否删除成功 } //大批量的插入数据, 批量删除更新也是类似的操作 @Test void testBulkRequest() { BulkRequest bulkRequest = new BulkRequest(); bulkRequest.timeout("10s"); ArrayList userList = new ArrayList(); userList.add(new User("cyh3", 20)); userList.add(new User("cyh4", 23)); for(int i = 0; i < userList.size(); i++) { bulkRequest.add( new IndexRequest("cyh_index") .id("" +(i+1)) //这句不设置则是随机数 .source(JOSN.toJSONString(userList.get(i), XContentType.JSON)); ); } BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT); //打印bulkResponse.hasFailures(), 返回false表示成功 } //查询 //SearchRequest 搜索请求 //SearchSourceBuilder 条件构建 //HighLightBuilder 构建高亮 //TermQueryBuilder 构建精确查询 //MatchAllQueryBuilder 构建匹配查询 @Test void testSearch() { SearchRequest searchRequest = new SearchRequest("cyh_index"); //构建搜索条件 SearchSourceBuilder sourceBuilder new SearchSourceBuilder(); //查询条件,我们可以使用QueryBuilders工具来实现 //QueryBuilders.termQuery() 精确查询 //QueryBuilder.matchAllQuery() 匹配所有 TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "cyh"); sourceBuilder.query(termQueryBuilder); sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDES)); //分页 sourceBuilder.from(0); sourceBuilder.size(10); searchRequest.source(sourceBuilder); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); //打印searchResponse.getHits() } //高亮的部分代码 @Test void testHighLight() { HighlightBuilder highlightBuilder = new HighlightBuilder(); highlightBuilder.field("title"); //需要高亮的字段 highlightBuilder.requireFieldMetch(false); //取消多个高亮显示 highlightBuilder.preTags(""); //前缀 highlightBuilder.postTags(""); //后缀 sourceBuilder.highlighter(highlightBuilder); Map highlightFields = hit.getHighlightFields(); //高亮字段 HighlightField title = highlightFields.get("title"); Map sourceAsMap = hit.getSourceAsMap(); //非高亮字段 //将高亮字段替换掉原来非高亮字段 } //java从网站上爬取数据进行清洗的依赖包 org.jsoup jsoup 1.10.2 第二个视频的方式 API的方式 private TransportClient client = null; @BeforeTest public void getClient() { Settings settings = Settings.builder().put("aa", "bb").build(); TransportAddress transportAddress1 = new TransportAddress(InetAddress.getByName("node01"), 9300); client = new PreBuiltTransportClient(settings) .addTransportAddress(transportAddress1) .addTransportAddress(transportAddress2); } @AfterTest public void closeClient() { client.close(); } @Test public void createIndex1() { IndexRequstBuilder indexRequestBuilder = client.prepareIndex("aa", "bb", "1").setSource(json, XContentType.JSON); indexRequestBuilder.get(); } @Test public void createIndex2() { IndexRequstBuilder indexRequestBuilder = client.prepareIndex("aa", "bb", "2").setSource(map, XContentType.JSON); indexRequestBuilder.get(); } @Test public void createIndex3() { IndexRequstBuilder indexRequestBuilder = client.prepareIndex("aa", "bb", "3").setSource(new XContentFactory().jsonBuilder().startObject().field("name", "cyh").field("age", "10").endObject()); indexRequestBuilder.get(); } @Test public void createIndex4() { IndexRequstBuilder indexRequestBuilder = client.prepareIndex("aa", "bb", "4").setSource(JSONObject.toJSONString(user), XContentType.JSON); indexRequestBuilder.get(); } //批量添加 @Test public void addBatch() { BulkRequest bulkRequestBuilder = client.prepareBulk(); IndexRequstBuilder i1 = client.prepareIndex("aa", "bb", "5").setSource(json1, XContentFactory.JSON); IndexRequstBuilder i2 = client.prepareIndex("aa", "bb", "6").setSource(json2, XContentFactory.JSON); BulkRequestBuilder add = bulkRequestBuilder.add(i1).add(i2); add.get(); } //更新数据 @Test public void updateIndex() { client.prepareUpdate("aa", "bb", "2").setDoc(json, XContentFactory.JSON).get(); } //删除 @Test public void deleteIndex() { client.prepareDelete("aa", "bb", "2").get(); } //删除整个索引库 @Test public void deleteAllDB() { client.admin().indices().prepareDelete("aa").execute().actionGet(); } //查询 @Test public void getBySystemId() { GetRequestBuilder builder = client.prepareGet("aa", "bb", "2"); GetResponse res = builder.get(); } //查询所有数据 @Test public void queryAll() { SearchResponse res = client.prepareSearch("aaa").setTypes("bb").setQuery(QueryBuilders.matchAllQuery()).get(); res.getHits(); } //范围查询 @Test public void queryRange() { SearchResponse res = client.prepareSearch("aaa").setTypes("bb").setQuery(QueryBuilders.rangeQuery("age").gt(18).lt(28)).get(); res.getHits(); } //词条查询 @Test public void queryTerm() { SearchResponse res = client.prepareSearch("aaa").setTypes("bb").setQuery(QueryBuilders.termQuery("say", "熟悉")).get(); res.getHits(); } //模糊查询,主要查询英文字母拼写错误的情况 @Test public void queryFuzzy() { SearchResponse res = client.prepareSearch("aaa").setTypes("bb").setQuery(QueryBuilders.fuzzyQuery("say", "helol").fuzziness(Fuzziness.TWO)).get(); res.getHits(); } //通配符查询 用.和* @Test public void queryWildCard() { SearchResponse res = client.prepareSearch("aaa").setTypes("bb").setQuery(QueryBuilders.wildcardQuery("say", "hel*")).get(); res.getHits(); } //多条件查询: booleanQuery @Test public void queryWildCard() { RangeQueryBuilder age = QueryBuilders.rangeQuery("age").get(18).lt(28); TermQueryBuilder sex = QueryBuilders.termQuery("sex", "1"); SearchResponse res = client.prepareSearch("aaa").setTypes("bb").setQuery(QueryBuilders.boolQuery().should(age).must(sex)).get(); } //分页查询 @Test public void queryPage() { SearchResponse res = client.prepareSearch("aaa").setTypes("bb").setQuery(QueryBuilders.matchAllQuery()).addSort("id", SortOrder.ASC).setFrom(2).setSize(5); } //高亮查询 @Test public void queryHighLighter() { HighlightBuilder h = new HighlightBuilder(); h.field("say").preTags(""); SearchResponse res = client.prepareSearch("aaa").setTypes("bb").setQuery(QueryBuilders.matchAllQuery()).highlighter(h).get(); } //分组查询 @Test public void queryGroup() { TermsAggregationBuilder a = AggregationBuilders.terms("nn").field("mm"); SearchResponse res = client.prepareSearch("aaa").setTypes("bb").addAggregation(a).get(); } //统计数量, 最值,平均值,分组求和,聚合排序 @Test public void queryCount() { } # ELK日志:第二篇视频: elasticSearch 全文检索框架 logstash 日志采集框架 kibana 日志界面显示框架 elasticSearch不能用root用户来启动,必须用普通用户来安装启动 使用root用户给机器创建普通用户: useradd es mkdir -p /export/servers/es chown -R es:es /export/servers/es //root用户创建的东西,其他用户不能用,所以改成es用户es组可以使用 passwd es 回车, 设置密码 为普通用户es创建sudo权限 用root用户执行下面命令 visudo 找到root ALL=(ALL) ALL, 下面增加一行: es ALL=(ALL) ALL 表示es用户可以在任何地方使用任何命令 上传下载安装包解压 断电连接linux的工具, 重新连接,用es用户登录,执行下面命令 cd /home/es/ wget https://压缩包地址 tar -zxf elasticSearch.tar.gz -C /export/server/es/ 修改配置文件: 修改elasticsearch.yml cd /export/servers/es/elasticsearch-6.7.0/config mkdir -p /export/servers/es/elasticsearch-6.7.0/logs mkdir -p /export/servers/es/elasticsearch-6.7.0/datas rm -rf elasticsearch.yml vim elasticsearch.yml cluster.name: myes node.name: node01 //主机名 path.data: /export/servers/es/elasticsearch-6.7.0/datas path.logs: /export/servers/es/elasticsearch-6.7.0/logs network.host: 192.168.52.100 //当前服务器的地址 http.port 9200 discovery.zen.ping.unicast.hosts: ["node01", "node02", "node03"] bootstrap.system_call_filter: flase bootstrap.memory_lock:false http.cors.enabled: true http.cors.allow-origin: "*" 修改jvm.option 里面-Xms1g和Xmx1g,表示需要的内存,可以改成-Xms256m 和 -Xmx256m 使用命令scp -r elasticsearch-6.7.0/ node03:$PWD 将这个文件夹拷贝到其它服务器上去, 修改里面的node.name和network.host, 一共有node01,node02,node03的三台机器 解决报错的三个问题 解决问题一 sudo vi /etc/security/limits.conf * soft nofile 65536 * hard nofile 131072 * soft nproc 2048 * hard nproc 4096 解决问题二 sudo vi /etc/security/limits.d/90-nproc.conf 将* soft nproc 1024改成 * soft nproc 4096 解决问题三 每次启动es都要执行下面的命令 sudo sysctl -w vm.max_map_count=262144 启动es服务器 nohup /export/servers/es/elasticsearch-6.7.0/bin/elasticsearch 2>&1 & jps 浏览器访问:http://node01:9200/?pretty 安装elasticsearch-head插件 1.安装node.js 下载安装包 cd /home/es/ wget https://node的安装包地址 tar -zxvf node.tar.gz -C /export/servers/es/ 创建软连接 sudo ln -s /export/servers/es/node-v8.1.0-linux-x64/lib/node_moduls/npm/bin/npm-cli.js /usr/local/bin/npm sudo ln -s /export/servers/es/node-v8.1.0-linux-x64/bin/node /usr/local/bin/node 修改环境变量 sudo vim /etc/profile export NODE_HOME=/export/servers/es/node-v8.1.0-linux-x64 export PATH=:$PATH:$NODE_HOME/bin 2.安装elasticsearch-head插件 将elasticsearch-head-compile-after.tar.gz 上传到node01机器的/home/es路径下面 解压安装包 cd /home/es/ tar -zxvf xxx.tar.gz -C /export/servers/es 修改Gruntfile.js cd /export/servers/es/elasticsearch-head vim Gruntfile.js 将hostname改成 hostname: '192.168.100.100' 自己机器的ip 修改app.js cd /export/servers/es/elasticsearch-head/_site vim app.js 将http://localhost:9200改成http://node01:9200 启动head服务 cd /export/servers/es/elaticsearch-head/node_modules/grunt/bin 进程前台启动 ./grunt server 进程后台启动 nohub ./grunt server >/dev/null 2>&1 & 浏览器访问: http://node01:9100 安装kibana 下载安装包 cd /home/es/ wget https://安装包地址 tar -zxf xxx.tar.gz -C /export/servers/es/ 修改配置文件 cd /export/servers/es/kibana/config/ vi kibana.yml server.host: "node01" elasticsearch.hosts: ["http://node01:9200"] 启动 cd /export/servers/es/kibana/ nohup bin/kibana >/dev/null 2>&1 & 浏览器访问: http://node01:5601 等一段时间多刷新几次才会出现 安装ik分词器 cd /home/es wget https://分词器安装包的地址 mkdir /export/servers/es/elasticsearch-6.7.0/plugins/analysis-ik/ unzip 是一个zip的包,解压,将解压的内容复制到上面创建的文件夹中 重启elasticsearch elasticSearch安装sql插件,就可以像使用sql语句一样来查询语句,https://github.com/NLPchina/elasticsearch-sql/ Logstash的安装, 在elasticSearch的官网中找到Logstash, 里面有三个重要的插件:Input plugins 用于采集来源, Output plugins采集的数据保存到哪里, Filter plugins 对采集的数据加工和转换 Logstash的安装: cd /home/es/ wget https://logstash的地址 tar -zxf logstash.tar.gz -C /export/servers/es/ 配置input和output插件, 查看官网 bin/logstash -e 'input {stdin{}} output{stdout{codec => rubydebug}}' ELK的配置: https://blog.csdn.net/janthinasnail/article/details/111064029 https://blog.csdn.net/chj_1224365967/article/details/119805341