ES入门与进阶
1.ES下载地址
https://mirrors.huaweicloud.com/elasticsearch/
解压运行,出现如下所示证明安装成功
2.安装head插件
https://github.com/mobz/elasticsearch-head
运行,出现如下结果,安装成功
#配置跨域
http.cors.enabled: true
http.cors.allow-origin: "*"
3.安装kibana
https://mirrors.huaweicloud.com/kibana
4.下载ik分词器
https://github.com/medcl/elasticsearch-analysis-ik/releases
ik分词器属性介绍
ik_smart:最少切分
ik_max_word:最细粒度划分
5.ES字段的基本类型
字符串类型:text,keyword
数值类型: long,integer,short,byte,double,float,half,float,scaled,float
日期类型: date
布尔类型:boolean
二进制类型: binary
6.ES操作
1 #匹配 2 #按照条件匹配 3 #精确匹配 4 #区间范围匹配 5 #区间字段过滤 6 #多条件查询 7 #高亮查询 8 GET _analyze 9 { 10 "analyzer": "ik_smart", 11 "text": "订单管理系统" 12 } 13 GET _analyze 14 { 15 "analyzer": "ik_max_word", 16 "text": "订单管理系统" 17 } 18 19 PUT /order/type1/1 20 { 21 "orderId":"12346789", 22 "source_order_id":"123456789" 23 } 24 25 PUT /product 26 { 27 "mappings": { 28 "properties": { 29 "orderId":{ 30 "type": "integer" 31 }, 32 "productName":{ 33 "type": "text" 34 }, 35 "createDate":{ 36 "type": "date" 37 } 38 } 39 } 40 } 41 GET /order 42 #创建文档默认_doc 43 PUT /logistic/_doc/1 44 { 45 "logisticId":1, 46 "name":"xl", 47 "date":"2021-01-07" 48 } 49 GET /logistic 50 #通过_cat查看索引很多信息 51 #获取状态信息 52 GET /_cat/health 53 #查看版本信息 54 GET /_cat/indices 55 #更新 56 PUT /order/type1/1 57 { 58 "orderId":"123467890", 59 "source_order_id":"123456789" 60 } 61 #修改后版本号增加 62 GET /order/type1/1 63 #使用POST方式进行修改需要带 _update 64 POST /order/type1/1/_update 65 { 66 "doc": { 67 "orderId": "11111111111" 68 } 69 } 70 #删除index 71 DELETE /order 72 #删除索引下的内容 73 DELETE /logistic/_doc/1 74 { 75 "logisticId":"1" 76 } 77 78 GET /logistic/_doc/1 79 #重点 80 #—————————基本操作—————————— 81 #创建用户索引 82 PUT /user/_doc/1 83 { 84 "userId":"007", 85 "name":"xl", 86 "date":"2010-11-12" 87 } 88 89 PUT /user/_doc/2 90 { 91 "userId":"008", 92 "name":"李四", 93 "date":"2010-11-12" 94 } 95 PUT /user/_doc/3 96 { 97 "userId":"008", 98 "name":"王五", 99 "date":"2010-11-12" 100 } 101 PUT /user/_doc/4 102 { 103 "userId":"0010", 104 "name":"赵六", 105 "date":"2010-11-12", 106 "hobby":["eat","play"] 107 } 108 109 #获取数据 110 GET /user/_doc/1 111 #修改数据 112 #PUT修改数据,当字段不全时,会造成其它字段置空【覆盖】 113 PUT /user/_doc/1 114 { 115 "name":"和三" 116 } 117 GET /user/_doc/1 118 119 PUT /user/_doc/1 120 {"userId":"007", 121 "name":"和尚", 122 "date":"2010-11-12", 123 "hobby":["eat","play"] 124 } 125 126 #推荐使用POST _update进行数据更新[在doc中更新] 127 POST /user/_doc/2/_update 128 { 129 "doc":{ 130 "name":"车九" 131 } 132 } 133 GET /user 134 135 136 #搜索【条件搜索】 137 GET /user/_search?q=name:李四 138 GET /user/_search?q=name:赵六 139 GET /user/_search?q=date:"2010-11-12" 140 141 #复杂操作【排序,分页,高亮,模糊查询,精准查询】 142 #属性query 143 GET /user/_search 144 { 145 "query": { 146 "match": { 147 "name": "李四" 148 } 149 } 150 } 151 #hits: 152 #索引和文档的信息 153 #查询的结果总数 154 #查询的具体文档 155 156 #属性 _source 查询部分字段信息 select * ---> select name 157 GET /user/_search 158 { 159 "query": { 160 "match": { 161 "name":"赵" 162 } 163 }, 164 "_source": ["name","date"] 165 } 166 167 #sort 排序 168 #分页 form 起始值,size 每页锁多少 169 GET /user/_search 170 { 171 172 "_source": ["name","date"], 173 "sort": [ 174 { 175 "userId.keyword": { 176 "order": "desc" 177 } 178 } 179 ], 180 181 "from": 0, 182 "size": 2 183 } 184 185 #查询匹配条件,多条检查询 186 #must [必须都满足] 如 MySQL中的where a=b and c=d 187 #should [满足其中一个即可] 如 MySQL中的where a=b or c=d 188 #must_not [查询非条件] 189 GET user/_search 190 { 191 "query": { 192 "bool": { 193 "must_not": [ 194 { 195 "match": { 196 "name":"王五" 197 } 198 199 },{ 200 "match": { 201 "name": "赵六" 202 } 203 } 204 ] 205 } 206 } 207 } 208 209 #filter [查询条件过滤] 210 #rage 范围过滤 211 #type 按照类型过滤 212 #ids 使用id进行过滤 213 GET user/_search 214 { 215 "query": { 216 "bool": { 217 "must_not": [ 218 { 219 "match": { 220 "name":"王五" 221 } 222 223 },{ 224 "match": { 225 "name": "赵六" 226 } 227 } 228 ], 229 "filter": { 230 231 "range": { 232 "userId": { 233 "gte": 0, 234 "lte": 2 235 } 236 } 237 } 238 } 239 } 240 } 241 242 #多条件查询 243 #查询属性hobby中包含eat字段的文档 244 #多个条件使用空格隔开【eat play】 245 #获取score分数值最高的即可 246 GET /user/_search 247 { 248 "query": { 249 "match": { 250 "hobby": "eat" 251 } 252 } 253 } 254 #精确查询 255 #term 查询通过倒排索指定的词条进行精确查找 256 #match 会使用分词器解析【先分析doc.再通过分析的doc进行查询】 257 #所以trem的效率高 258 259 #注意 ********************** 260 #类型中 text类型会被分词器解析,keyword类型不会被分词器解析 261 262 PUT /person 263 { 264 "mappings": { 265 "properties": { 266 "name":{ 267 "type": "text" 268 }, 269 "desc":{ 270 "type": "keyword" 271 } 272 } 273 } 274 } 275 276 POST /person/_doc/1 277 { 278 "name":"赵三", 279 "desc":"撕票,面值" 280 } 281 282 POST /person/_doc/2 283 { 284 "name":"李四", 285 "desc":"撕票,金钱" 286 } 287 288 POST /person/_doc/3 289 { 290 "name":"王五", 291 "desc":"中古欧工" 292 } 293 294 POST /person/_doc/4 295 { 296 "name":"张六", 297 "desc":"中古欧工滴滴滴" 298 } 299 300 #使用_analyze进行分析查询 301 GET _analyze 302 { 303 "analyzer": "keyword", 304 "text": "中古欧工滴滴滴" 305 } 306 307 GET _analyze 308 { 309 "analyzer": "standard", 310 "text": "中古欧工滴滴滴" 311 } 312 313 314 GET /person/_search 315 { 316 "query": { 317 "match": { 318 "desc": "中古欧工滴滴滴" 319 } 320 } 321 } 322 323 #使用trem进行精确值查询 324 GET person/_search 325 { 326 "query": { 327 "term": { 328 "desc": { 329 "value": "中古欧工滴滴" 330 } 331 } 332 } 333 } 334 335 #高亮查询 336 #搜索的结果可以高亮显示 337 #highlight 338 #在highlight中使用 pre_tags post_tags:进行自定义标签设置 339 GET person/_search 340 { 341 "query": { 342 "match": { 343 "name": "李四" 344 } 345 }, 346 "highlight": { 347 "fields": { 348 "name": {} 349 } 350 } 351 }
7.使用springboot操作ES
1.maven依赖
https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html
<dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.6.2</version> </dependency>
2.使用对象,初始化
RestHighLevelClient client = new RestHighLevelClient( RestClient.builder( new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 9201, "http"))); client.close();
3.使用
1 @Autowired 2 @Qualifier("restHighLevelClient") 3 private RestHighLevelClient client; //类型一样但是名称不一样,此时需要使用Qualifuer进行方法名的指定 4 //@Autowired 5 //private RestHighLevelClient restHighLevelClient; 6 7 //1.创建索引请求 8 @Test 9 void createIndex() throws IOException { 10 11 CreateIndexRequest indexRequest = new CreateIndexRequest("xl_person"); 12 CreateIndexResponse indexResponse = client.indices().create(indexRequest, RequestOptions.DEFAULT); 13 System.out.println(indexResponse); 14 15 } 16 17 //获取索引 18 @Test 19 public void getIndex() throws IOException { 20 GetIndexRequest getIndexRequest = new GetIndexRequest("xl_person"); 21 boolean exists = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT); 22 System.out.println(exists); 23 } 24 25 //删除索引 26 @Test 27 public void deleteIndex() throws IOException { 28 DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("xl_person"); 29 AcknowledgedResponse delete = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT); 30 System.out.println(delete.isAcknowledged()); 31 } 32 33 //创建文档 34 @Test 35 public void createDoc() throws IOException { 36 Person person = new Person("xl", 22); 37 String personStr = JSON.toJSONString(person); 38 //创建请求 39 IndexRequest request = new IndexRequest("xl_person"); 40 //设置ID 41 request.id("1"); 42 request.timeout(TimeValue.timeValueSeconds(1L)); 43 //放入数据到请求中 44 request.source(personStr, XContentType.JSON); 45 //发送请求,获取响应结果 46 IndexResponse response = client.index(request, RequestOptions.DEFAULT); 47 System.out.println(response.status()); 48 System.out.println(response.toString());//CREATED 49 50 } 51 52 //操作文档 53 @Test 54 public void optDoc() throws IOException { 55 //获取 56 GetRequest getRequest = new GetRequest("xl_person", "1"); 57 //不获取返回的_source_上下文 58 //getRequest.fetchSourceContext(new FetchSourceContext(false)); 59 ////设置stored为none 60 //getRequest.storedFields("_none_"); 61 boolean exists = client.exists(getRequest, RequestOptions.DEFAULT); 62 if (exists) { 63 //获取文档信息 64 GetResponse response = client.get(getRequest, RequestOptions.DEFAULT); 65 System.out.println(response.getSourceAsString()); 66 System.out.println(response.getId()); 67 68 //更新操作 69 UpdateRequest updateRequest = new UpdateRequest("xl_person", "1"); 70 updateRequest.timeout("1s"); 71 Person person = new Person("lx", 30); 72 updateRequest.doc(JSON.toJSONString(person), XContentType.JSON); 73 UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT); 74 System.out.println(updateResponse.status()); 75 System.out.println(updateResponse.toString()); 76 77 //删除 78 DeleteRequest deleteRequest = new DeleteRequest("xl_person", "1"); 79 DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT); 80 System.out.println(deleteResponse.status()); 81 System.out.println(deleteResponse.toString()); 82 } 83 84 85 } 86 87 //批量操作数据 88 @Test 89 public void optBulkDoc() throws IOException { 90 BulkRequest bulkRequest = new BulkRequest(); 91 bulkRequest.timeout("1s"); 92 List<Person> personList = new ArrayList<>(); 93 personList.add(new Person("lx1", 12)); 94 personList.add(new Person("lx2", 13)); 95 personList.add(new Person("lx3", 14)); 96 personList.add(new Person("lx4", 15)); 97 personList.add(new Person("lx5", 16)); 98 personList.add(new Person("lx6", 17)); 99 for (int i = 0; i < personList.size(); i++) { 100 bulkRequest.add(new IndexRequest(ESConstant.XL_PERSON).id(i + 2 + "").source(JSON.toJSONString(personList.get(i)), XContentType.JSON)); 101 } 102 BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT); 103 System.out.println(bulk.hasFailures()); 104 } 105 106 //查询 107 //高亮显示 108 @Test 109 public void searchDoc() throws IOException { 110 SearchRequest searchRequest = new SearchRequest(ESConstant.XL_PERSON); 111 //构造搜索条件 112 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); 113 //================== 114 //查询条件可以使用QueryBuilder进行构建 115 // QueryBuilders.termQuery() 进行精确查询 116 //QueryBuilders.matchAllQuery() 匹配所有进行查询 117 TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "lx1"); 118 searchSourceBuilder.query(termQueryBuilder); 119 searchSourceBuilder.timeout(new TimeValue(20, TimeUnit.SECONDS)); 120 //将查询条件放入到请求中 121 searchRequest.source(searchSourceBuilder); 122 //构造请求获取响应 123 SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT); 124 //System.out.println(JSON.toJSONString(search.getHits())); 125 for (SearchHit hit : search.getHits()) { 126 System.out.println(hit.getSourceAsMap()); 127 } 128 129 }
4.ES搜索与高亮
@Service public class ESService { @Autowired @Qualifier("restHighLevelClient") private RestHighLevelClient client; @Autowired private HtmlParseUtil htmlParseUtil; //数据放入ES中 public boolean dataToEs(String keyword) throws IOException { List<Content> htmlInfos = htmlParseUtil.getHtmlInfo(keyword); BulkRequest request = new BulkRequest(); request.timeout("5ms"); htmlInfos.forEach(htmlInfo -> { request.add(new IndexRequest(ESConstant.JS_GOODS) .source(JSON.toJSONString(htmlInfo), XContentType.JSON) ); }); BulkResponse bulk = client.bulk(request, RequestOptions.DEFAULT); return !bulk.hasFailures(); } //获取数据实现搜索功能 public List<Map<String, Object>> search(String keyword, int pageNo, int pageSize) throws IOException { if (pageNo <= 1) { pageNo = 1; } //条件搜索 SearchRequest request = new SearchRequest(ESConstant.JS_GOODS); //条件构造 SearchSourceBuilder builder = new SearchSourceBuilder(); //分页查询 builder.from(pageNo); builder.size(pageSize); //进行精准查询 TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", keyword); builder.query(termQueryBuilder); builder.timeout(new TimeValue(60, TimeUnit.SECONDS)); //高亮设置 HighlightBuilder highlightBuilder = new HighlightBuilder(); //title 显示高亮 highlightBuilder.field("title"); //只需第一个显示高亮 highlightBuilder.requireFieldMatch(false); //高亮标签 highlightBuilder.preTags("<span style='color:red'>"); highlightBuilder.postTags("</span>"); builder.highlighter(highlightBuilder); //将构造条件放入请求中 request.source(builder); //执行搜索 SearchResponse response = client.search(request, RequestOptions.DEFAULT); List<Map<String, Object>> list = new ArrayList<>(); //Stream.of(response.getHits().getHits()).collect(Collectors.toMap(hit->{})) for (SearchHit searchHit : response.getHits().getHits()) { //解析高亮字段 Map<String, HighlightField> fields = searchHit.getHighlightFields(); HighlightField title = fields.get("title"); //拿到存储的数据 Map<String, Object> sourceAsMap = searchHit.getSourceAsMap(); //将原来的title替换为新高亮的title if (title != null) { Text[] fragments = title.fragments(); String newTitle = ""; for (int i = 0; i < fragments.length; i++) { newTitle += fragments[i]; } sourceAsMap.put("title", newTitle); } list.add(sourceAsMap); } //Stream.of(response.getHits().getHits()).map(SearchHit::getSourceAsMap).collect(Collectors.toList()); return list; } }