ElasticSearch
1、安装(Windows)?
首先准备几个包
elasticsearch-7.6.1-windows-x86_64
elasticsearch-analysis-ik-7.6.1
elasticsearch-head-master`在这里插入代码片`
kibana-7.6.1-windows-x86_64
2、环境安装?
需要安装node环境,启动head需要node环境。
通过cnpm install安装node_modules
cnpm run start启动即可启动head
3、解决跨域问题?
启动elasticsearch和head之后会发现head连接不上9200,需要解决跨域问题
在elasticsearch安装包中找到elasticsearch.yml中添加两行即可,如下:
http.cors.enabled: true
http.cors.allow-origin: "*"
4、安装kibana?
解压之后的kibana里面就有node_modules,直接启动bat即可。
首先进去是英文的,所以需要修改kibana.yml里面最后一行中的en改成zh-CN之后,重启即可。
5、IK分词器?
将ik分词器的解压包解压之后放进elasticsearch的plugins里面就可以了,可以自定义分词器,只需在config里面添加一个dic文件,然后在IKAnalyzer.cfg.xml中指定文件就行。
在IKAnalyzer.cfg.xml中的配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">wuheng.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
常用的分词器
ik_smart:最粗粒度的拆分。
如:
GET /_analyze
{
"analyzer": "ik_smart",
"text": "中华人民共和国人民大会堂"
}
结果:
{
"tokens" : [
{
"token" : "中华人民共和国",
"start_offset" : 0,
"end_offset" : 7,
"type" : "CN_WORD",
"position" : 0
},
{
"token" : "人民大会堂",
"start_offset" : 7,
"end_offset" : 12,
"type" : "CN_WORD",
"position" : 1
}
]
}
ik_max_word:最细粒度的拆分
如:
GET /_analyze
{
"analyzer": "ik_max_word",
"text": "中华人民共和国人民大会堂"
}
结果:
{
"tokens" : [
{
"token" : "中华人民共和国",
"start_offset" : 0,
"end_offset" : 7,
"type" : "CN_WORD",
"position" : 0
},
{
"token" : "中华人民",
"start_offset" : 0,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "中华",
"start_offset" : 0,
"end_offset" : 2,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "华人",
"start_offset" : 1,
"end_offset" : 3,
"type" : "CN_WORD",
"position" : 3
},
{
"token" : "人民共和国",
"start_offset" : 2,
"end_offset" : 7,
"type" : "CN_WORD",
"position" : 4
},
{
"token" : "人民",
"start_offset" : 2,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 5
},
{
"token" : "共和国",
"start_offset" : 4,
"end_offset" : 7,
"type" : "CN_WORD",
"position" : 6
},
{
"token" : "共和",
"start_offset" : 4,
"end_offset" : 6,
"type" : "CN_WORD",
"position" : 7
},
{
"token" : "国人",
"start_offset" : 6,
"end_offset" : 8,
"type" : "CN_WORD",
"position" : 8
},
{
"token" : "人民大会堂",
"start_offset" : 7,
"end_offset" : 12,
"type" : "CN_WORD",
"position" : 9
},
{
"token" : "人民大会",
"start_offset" : 7,
"end_offset" : 11,
"type" : "CN_WORD",
"position" : 10
},
{
"token" : "人民",
"start_offset" : 7,
"end_offset" : 9,
"type" : "CN_WORD",
"position" : 11
},
{
"token" : "大会堂",
"start_offset" : 9,
"end_offset" : 12,
"type" : "CN_WORD",
"position" : 12
},
{
"token" : "大会",
"start_offset" : 9,
"end_offset" : 11,
"type" : "CN_WORD",
"position" : 13
},
{
"token" : "会堂",
"start_offset" : 10,
"end_offset" : 12,
"type" : "CN_WORD",
"position" : 14
}
]
}
6、SpringBoot操作Elasticsearch
创建一个springboot项目,添加依赖
dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
需要修改一下elasticsearch版本和安装的版本对应
<properties>
<elasticsearch.version>7.6.1</elasticsearch.version>
</properties>
创建用户类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String filename;
private String address;
private Integer age;
}
编写配置类
@Configuration
public class ElasticSearchConfig {
@Value("${elastic.hostname}")
private String hostname;
@Value("${elastic.port}")
private String port;
@Bean
public RestHighLevelClient restHighLevelClient(){
RestHighLevelClient restHighLevelClient= new RestHighLevelClient(
RestClient.builder(
new HttpHost(hostname, Integer.parseInt(port),"http")));
return restHighLevelClient;
}
}
hostname和port为elasticsearch的地址和端口。
配置完成之后就可以进行操作了。
package com.wuheng.elasticsearch.elasticsearchtest;
import com.alibaba.fastjson.JSON;
import com.sun.org.apache.regexp.internal.RE;
import com.wuheng.elasticsearch.pojo.Other;
import com.wuheng.elasticsearch.pojo.User;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
@RunWith(SpringRunner.class)
@SpringBootTest
@SuppressWarnings("all")
public class ElasticSearchTest01 {
@Autowired
@Qualifier("restHighLevelClient")
private RestHighLevelClient client;
/*
解释:
* 创建索引 CreateIndexRequest
* 删除索引 DeleteIndexRequest
* 查询是否存在索引 GetIndexRequest
*
* client.indices():用来操作index的,如get、create、delete
*
*
* */
//创建索引
@Test
public void CreateIndexRequest() throws IOException {
CreateIndexRequest request = new CreateIndexRequest("wuheng");
CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
System.out.println(response);
}
//查询索引是否存在
@Test
public void existRequest() throws IOException {
GetIndexRequest request=new GetIndexRequest("wuheng");
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(exists);
}
//删除索引
@Test
public void DeleteIndexRequest() throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest("wuheng");
AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
System.out.println(response);
}
/*
*
* {
"_index": "wuheng",
"_type": "_doc",
"_id": "5lb-y3kBS7iIP477fCur",
"_version": 1,
"_score": 1,
"_source": {
"address": "武汉",
"age": 25,
"filename": "吴恒"
}
}
*
* */
//添加文档
@Test
public void addDocument() throws IOException {
//创建连接请求
IndexRequest request = new IndexRequest("wuheng");
//创建对象
User user = new User("吴恒", "武汉", 25);
//可以设置,如果不设置就给一个默认值,如 5lb-y3kBS7iIP477fCur
request.id("1");
//请求超时不执行
request.timeout("10s");
//将对象转换成JSON格式数据放入请求中。即放入source中
request.source(JSON.toJSONString(user), XContentType.JSON);
//客户端传递请求
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
System.out.println(response.toString());
System.out.println(response.status());
}
//修改文档
@Test
public void updateDocument() throws IOException {
//获取索引为wuheng,id为1的文档
UpdateRequest request=new UpdateRequest("wuheng","1");
//请求超时不执行
request.timeout("5s");
//修改的信息
User user=new User();
user.setAge(29);
user.setFilename("张三三");
//将修改的信息放入请求,修改的时候调用doc();
request.doc(JSON.toJSONString(user), XContentType.JSON);
request.fetchSource(true);
UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
System.out.println(update.toString());
System.out.println(update.getIndex());
System.out.println(update.getGetResult());
System.out.println(update.status());
}
//删除文档
@Test
public void DeleteDocument() throws IOException {
//删除索引为wuheng中id为1的文档(数据)
DeleteRequest request=new DeleteRequest("wuheng","1");
DeleteResponse delete = client.delete(request, RequestOptions.DEFAULT);
System.out.println(delete.status());
System.out.println(delete.toString());
}
//查询文档
@Test
public void SelectDocument() throws IOException {
//查询索引为wuheng中id为1的文档(数据),存在则返回数据,不存在返回为null
GetRequest request=new GetRequest("wuheng","5lb-y3kBS7iIP477fCur");
GetResponse response = client.get(request, RequestOptions.DEFAULT);
System.out.println(response.getSource());
}
//批量添加
@Test
public void BulkDocument() throws IOException {
BulkRequest request = new BulkRequest("wuheng");
request.timeout("10s");
request.estimatedSizeInBytes();
ArrayList<User> userList = new ArrayList<>();
User user1=new User("张三","武汉",21);
User user2=new User("李四","上海",28);
User user3=new User("王五","天津",15);
User user4=new User("赵六","内蒙古",5);
User user5=new User("李七","武汉",45);
Collections.addAll(userList,user1,user2,user3,user4,user5);
userList.forEach((u)->request.add(new IndexRequest().source(JSON.toJSONString(u),XContentType.JSON)));
BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);
System.out.println(response.status());
}
//搜索
@Test
public void SearchDocument() throws IOException {
//创建搜锁索引为wuheng的请求
SearchRequest request=new SearchRequest("wuheng");
System.out.println("======================匹配所有=====================");
allRequest(request);
gethit(request);
System.out.println("======================精确查询=====================");
termRequest(request);
gethit(request);
System.out.println("======================范围查询=====================");
fanweiRequest(request);
gethit(request);
System.out.println("======================多条件查询=====================");
manyTiaoJianRequest(request);
gethit(request);
System.out.println("======================高亮=====================");
HighSearch(request);
gethit(request);
}
private void gethit(SearchRequest request) throws IOException {
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
System.out.println(response);
}
private void termRequest(SearchRequest request){
//条件构造器
SearchSourceBuilder builder=new SearchSourceBuilder();
TermQueryBuilder termQuery = QueryBuilders.termQuery("filename", "恒");
builder.query(termQuery);
request.source(builder);
}
private void allRequest(SearchRequest request) {
//条件构造器
SearchSourceBuilder builder=new SearchSourceBuilder();
//匹配所有
MatchAllQueryBuilder allQuery = QueryBuilders.matchAllQuery();
builder.query(allQuery);
//将查询条件放在请求中
request.source(builder);
}
private void fanweiRequest(SearchRequest request){
//条件构造器
SearchSourceBuilder builder=new SearchSourceBuilder();
RangeQueryBuilder rangeAge = QueryBuilders.rangeQuery("age").from(5).to(20);
builder.query(rangeAge);
request.source(builder);
}
/*
* must:必须满足的条件
* mustNot:必须不满足的条件
* should:等同于or的作用
* */
private void manyTiaoJianRequest(SearchRequest request){
SearchSourceBuilder builder = new SearchSourceBuilder();
RangeQueryBuilder q1 = QueryBuilders.rangeQuery("age").from(5).to(20);
TermQueryBuilder q2 = QueryBuilders.termQuery("address", "天");
BoolQueryBuilder qb1 = QueryBuilders.boolQuery().must(q1).mustNot(q2);
BoolQueryBuilder qb2 = QueryBuilders.boolQuery().must(q1).should(q2);
BoolQueryBuilder qb3 = QueryBuilders.boolQuery().must(q1).must(q2);
builder.query(qb1);
builder.query(qb2);
builder.query(qb3);
request.source(builder);
}
//高亮
public void HighSearch(SearchRequest request){
SearchSourceBuilder builder=new SearchSourceBuilder();
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("filename", "张三");
builder.query(matchQueryBuilder);
//高亮的操作
HighlightBuilder highlighter = new HighlightBuilder();
//设置高亮字段
highlighter.field("filename",1);
//设置前缀
highlighter.preTags("<em style='color:red>'");
//设置后缀
highlighter.postTags("</em>");
builder.highlighter(highlighter);
request.source(builder);
/*
返回的结果如下:
{
"took":2,
"timed_out":false,
"_shards":{
"total":1,
"successful":1,
"skipped":0,
"failed":0
},
"hits":{
"total":{
"value":1,
"relation":"eq"
},
"max_score":2.7725885,
"hits":[
{
"_index":"wuheng",
"_type":"_doc",
"_id":"J1asz3kBS7iIP477Zyye",
"_score":2.7725885,
"_source":{
"address":"武汉",
"age":21,
"filename":"张三"
},
"highlight":{
"filename":[
"<em style='color:red>'张</em><em style='color:red>'三</em>"
]
}
}
]
}
}
* */
/*
可以看到highlight中的filename已经加上了<em style="color:red"></em>的样式
*/
}
}