安装eshtml
项目添加maven依赖java
es客户端组件注入到spring容器中mysql
es与mysql表结构对比spring
索引的删除建立sql
文档的crud数据库
es能快速搜索的核心-倒排索引apache
基于倒排索引的精确搜索、全文搜索(重点)json
es集群springboot
安装文章app
1.<dependency> 2. <groupId>org.elasticsearch.client</groupId> 3. <artifactId>elasticsearch-rest-high-level-client</artifactId> 4. <version>7.10.2</version> </dependency>
1.package com.shuang.config; 2. 3.import org.apache.http.HttpHost; 4.import org.elasticsearch.client.RestClient; 5.import org.elasticsearch.client.RestHighLevelClient; 6.import org.springframework.context.annotation.Bean; 7.import org.springframework.context.annotation.Configuration; 8. 9.@Configuration //xml文件-bean 10.public class ElasticSearchClientConfig { 11. 12. @Bean 13. public RestHighLevelClient restHighLevelClient(){ 14. RestHighLevelClient client = new RestHighLevelClient( 15. RestClient.builder( 16. //多个集群,就new多个 17. new HttpHost("localhost", 9200, "http"))); 18. return client; 19. } 20.}
1)java代码建立索引
package com.shuang; @SpringBootTest class DemoApplicationTests { @Autowired private RestHighLevelClient restHighLevelClient; @Test void contextLoads() throws IOException { //1,建立索引表 CreateIndexRequest request=new CreateIndexRequest("shuangbao"); //2,客户端执行请求 IndicesClient,请求后得到响应 CreateIndexResponse createIndexResponse= restHighLevelClient.indices().create(request, RequestOptions.DEFAULT); System.out.println(createIndexResponse); } }
2)删除索引
@Test void testDeleteIndex() throws IOException { DeleteIndexRequest request=new DeleteIndexRequest(); AcknowledgedResponse delete =restHighLevelClient.indices().delete(request,RequestOptions.DEFAULT); System.out.println(delete); }
先新建索引,默认类型为_doc,创建文档结构json格式的属性有string类型的name,integer类型的age。
1.PUT /shuang_index1 2. { 3. "settings": { 4. "index": { 5. "number_of_replicas": "1", 6. "number_of_shards": "5" } 7. }, 8. "mappings": { 9. "test_type": { 10. "properties": { 11. "name": { 12. "type": "string", 13. }, 14. "age": { 15. "type": "integer" 16. } 17. } 18. } 19. } 20. }
插入一条文档id为1的数据
PUT shuang_index2/_doc/1 { "name":"shuang1", "age":"1" }
1)获取文档的信息,这里咱们获取文档id为1的信息
//获取文档的信息 @Test void testIsGetDocument() throws IOException { GetRequest getRequest=new GetRequest("shuang_index1","1"); //不获取返回的_source的上下文 GetResponse getResponse=restHighLevelClient.get(getRequest,RequestOptions.DEFAULT); System.out.println(getResponse.getSourceAsString());//打印文档的数据_source System.out.println(getResponse); //打印文档id为1的完整返回信息 } {"age":1,"name":"shuang1"} "_index":"shuang_index1","_type":"_doc","_id":"1","_version":1,"_seq_no":4,"_primary_term":1,"found":true,"_source":{"age":1,"name":"shuang1"}}
2)插入数据(数据来源能够是其余地方)
1.@Test 2.void testBulkRequest() throws IOException { 3. BulkRequest bulkRequest=new BulkRequest(); 4. bulkRequest.timeout("10s"); 5. 6. ArrayList<User> userList=new ArrayList<>(); 7. userList.add(new User("jiang1",1)); 8. userList.add(new User("jiang2",2)); 9. userList.add(new User("jiang3",3)); 10. userList.add(new User("jiang4",4)); 11. userList.add(new User("jiang5",5)); 12. userList.add(new User("jiang6",6)); 13. userList.add(new User("jiang7",7)); 14. userList.add(new User("jiang8",8)); 15. 16. //批处理请求 17. for(int i=0;i<userList.size();i++){ 18. //批量更新和删除,就在这里修改对应的请求就能够了 19. bulkRequest.add( 20. new IndexRequest("shuang_index1") 21. .id(""+(i+1)) 22. .source(JSON.toJSONString(userList.get(i)),XContentType.JSON)); 23. 24. } 25. BulkResponse bulkResponse=restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT); 26. 27. System.out.println(bulkResponse.hasFailures());//是否失败,返回false表明成功 28.}
3)删除文档信息
1.@Test 2.void testDeleteRequest() throws IOException { 3. DeleteRequest request=new DeleteRequest("shuang_index1","1"); 4. request.timeout("1s"); 5. 6. DeleteResponse deleteResponse=restHighLevelClient.delete(request,RequestOptions.DEFAULT); 7. System.out.println(deleteResponse.status()); 8. 9.}
4)更新文档信息
1.@Test 2. void testUpdateRequest() throws IOException { 3. UpdateRequest updateRequest=new UpdateRequest("shuang_index1","1"); 4. updateRequest.timeout("1s"); 5. 6. User user=new User("爽爽爽",18); 7. updateRequest.doc(JSON.toJSONString(user),XContentType.JSON); 8. 9. UpdateResponse updateResponse=restHighLevelClient.update(updateRequest,RequestOptions.DEFAULT); 10. 11. System.out.println(updateResponse.status()); 12. }
前面介绍了文档的查找,是普通的查找get方式的,须要指定_index、_type、_id。也就是根据id从正排索引中获取内容,肯定惟一文档。
但搜索search方式须要一种更复杂的模型,由于不知道查询会命中哪些文档。采用倒排索引能够知足复杂的搜索过程。
搜索也分精确值搜索和全文搜索,对数据创建索引和执行搜索的原理以下图所示:
Term(精确,不会被分词器解析,keyword类型的字段也不会被分词器解析)和match(全文,会被分词器解析)是两个经常使用的基于倒排索引的搜索类型。他们对应的java类主要有 TermQueryBuilder和MatchQueryBuilder。
精确搜索(在shuang_index1索引中,name字段为shuang1的文档)
1.@Test 2. void testSearch() throws IOException { 3. SearchRequest searchRequest=new SearchRequest("shuang_index1"); 4. //构建搜索条件 5. SearchSourceBuilder sourceBuilder=new SearchSourceBuilder(); 6. 7. TermQueryBuilder termQueryBuilder=QueryBuilders.termQuery("name","shuang1"); 8. 9. sourceBuilder.query(termQueryBuilder); 10. sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); 11. 12. searchRequest.source(sourceBuilder); 13. 14. SearchResponse searchResponse=restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT); 15. System.out.println(JSON.toJSONString(searchResponse.getHits())); 16. 17. for(SearchHit documentFields :searchResponse.getHits().getHits()){ 18. System.out.println(documentFields.getSourceAsMap()); 19. } 20. }
第二个输出是对搜索返回信息进行了提取关键字段。
全文搜索
1)在kibana上新建shuang_index2索引(至关于在navicat上去新建mysql数据库)
通常咱们不指定类型(系统会默认为_doc,es7不推荐使用了,es8将会移除类型,至关于mysql没有了表这个结构)。
设置里面的文档字段为name和age,它们类型为string与interger。
1.PUT /shuang_index2 2. { 3. "settings": { 4. "index": { 5. "number_of_replicas": "1", //设置副本数为1 6. "number_of_shards": "5" } //设置分片数为5 7. }, 8. "mappings": { 9. "test_type": { 10. "properties": { 11. "name": { 12. "type": "string", 13. }, 14. "age": { 15. "type": "integer" 16. } 17. } 18. } 19. } 20. }
2)插入数据(通常咱们是从数据仓库批量导入,java代码见上面文档的插入)
Kibana控制台也能够本身手动插入
1.PUT shuang_index2/_doc/5 2.{ 3. "name":"shuang e", 4. "age":"5" 5.}
这里shuang_index2为索引、_doc为类型、5表明文档id(大数据环境下,咱们通常不指定文档id,系统会随机生成一个文档id,惟一标识该文档)。它们分别对应mysql的数据库、表、行。name和age表明mysql字段中的列属性。文档结构必须为json格式。
3)搭建好索引结构后,咱们去用java代码实现一下
(内置分词器先把shuang bao分词为shuang 与 bao ,再去shuang_index2索引中去寻找,文档一、二、三、四、5分别有name=shuang a、b、c、d、e。他们事先也被分词器拆解了,只要有一个与上面对应,就搜索成功,而且会携带一个类似程度score返回)
1.@Test 2.void testSearch() throws IOException { 3. SearchRequest searchRequest=new SearchRequest("shuang_index2"); 4. //构建搜索条件 5. SearchSourceBuilder sourceBuilder=new SearchSourceBuilder(); 6. 7. MatchQueryBuilder matchQueryBuilder=QueryBuilders.matchQuery("name","shuang bao"); 8. sourceBuilder.query(matchQueryBuilder); 9. sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); 10. 11. searchRequest.source(sourceBuilder); 12. 13. SearchResponse searchResponse=restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT); 14. System.out.println(searchResponse); 15. 16. for(SearchHit documentFields :searchResponse.getHits().getHits()){ 17. System.out.println(documentFields.getSourceAsMap()); 18. } 19.}
返回结果:
{"took":770,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":{"value":5,"relation":"eq"},"max_score":0.08701137,"hits":[{"_index":"shuang_index2","_type":"_doc","_id":"1","_score":0.08701137,"_source":{"name":"shuang a","age":"1"}},{"_index":"shuang_index2","_type":"_doc","_id":"2","_score":0.08701137,"_source":{"name":"shuang b","age":"2"}},{"_index":"shuang_index2","_type":"_doc","_id":"3","_score":0.08701137,"_source":{"name":"shuang c","age":"3"}},{"_index":"shuang_index2","_type":"_doc","_id":"4","_score":0.08701137,"_source":{"name":"shuang d","age":"4"}},{"_index":"shuang_index2","_type":"_doc","_id":"5","_score":0.08701137,"_source":{"name":"shuang e","age":"5"}}]}} {name=shuang a, age=1} {name=shuang b, age=2} {name=shuang c, age=3} {name=shuang d, age=4} {name=shuang e, age=5}
如图3个es服务构成的集群,索引test分红了5片,一个副本(粗框的),而book一个分片一个副本。保证了若是有一个服务坏了,其余服务也能执行全部工做。
一个搜索请求必须询问请求的索引中全部分片的某个副原本进行匹配。假设一个索引有5个主分片,每一个主分片有1个副分片,共10个分片,一次搜索请求会由5个分片来共同完成,它们多是主分片,也多是副分片。也就是说,一次搜索请求只会命中全部分片副本中的一个。
ElasticSearch极简入门总结就结束了感谢您的阅读