Elasticsearch
Elasticsearch
安装与使用
下载地址
ElasticSearch: https://mirrors.huaweicloud.com/elasticsearch/?C=N&O=D
logstash: https://mirrors.huaweicloud.com/logstash/?C=N&O=D
kibana: https://mirrors.huaweicloud.com/kibana/?C=N&O=D
ik分词器: https://github.com/medcl/elasticsearch-analysis-ik/releases
可视化插件es head: https://github.com/mobz/elasticsearch-head
ElasticSearch
-
解压ElasticSearch
-
解压es head
-
在es head目录下npm install
-
启动ElasticSearch
-
访问http://localhost:9200/查看是否启动
-
在es head目录下npm run start
-
访问http://localhost:9100/进行连接
-
出现跨域问题,在elasticsearch.yml配置文件中加入允许跨域
http.cors.enabled: true http.cors.allow-origin: "*"
-
重新启动并连接
Kibana
-
Kibana版本要与Elasticsearch一致
-
解压kibana
-
启动kibana
-
访问http://localhost:5601/
-
使用中文界面,在kibana.yml中添加
i18n.locale: "zh-CN"
-
重新启动
ik分词器
-
ik分词器版本要与Elasticsearch一致
-
解压至Elasticsearch的plugins文件夹下
-
启动Elasticsearch
-
通过命令可以看到一使用的插件
elasticsearch-plugin list
-
在kibana的控制台中测试
-
最少切分ik_smart
GET _analyze { "analyzer": "ik_smart" , "text": "大头儿子" } //分词结果 { "tokens" : [ { "token" : "大头", "start_offset" : 0, "end_offset" : 2, "type" : "CN_WORD", "position" : 0 }, { "token" : "儿子", "start_offset" : 2, "end_offset" : 4, "type" : "CN_WORD", "position" : 1 } ] }
-
最细粒度划分ik_max_word
GET _analyze { "analyzer": "ik_max_word" , "text": "大头儿子" } //分词结果 { "tokens" : [ { "token" : "大头", "start_offset" : 0, "end_offset" : 2, "type" : "CN_WORD", "position" : 0 }, { "token" : "头儿", "start_offset" : 1, "end_offset" : 3, "type" : "CN_WORD", "position" : 1 }, { "token" : "儿子", "start_offset" : 2, "end_offset" : 4, "type" : "CN_WORD", "position" : 2 } ] }
-
添加自定义词汇,在config目录下新建my.dic,加入自定义词汇"肚肚肚"
-
在IKAnalyzer.cfg.xml中加载自定义词典
<entry key="ext_dict">my.dic</entry>
-
重启Elasticsearch
-
测试
GET _analyze { "analyzer": "ik_smart" , "text": "肚肚肚" } //分词结果 { "tokens" : [ { "token" : "肚肚肚", "start_offset" : 0, "end_offset" : 3, "type" : "CN_WORD", "position" : 0 } ] }
索引操作
新建索引 PUT
PUT /索引名/类型名/文档id
{请求体}
PUT /test1/type1/1
{
#数据请求体
"name": "pinked",
"age": 7
}
PUT test2
{
#规则请求体
"mappings": {
"properties": {
"name": {
"type": "text" #text属性的字段会被分词器解析,keyword属性的字段不会
},
"age": {
"type": "integer"
},
"birthday": {
"type": "date"
}
}
}
}
查询索引 GET
GET 索引名
GET test1
#查询结果
{
"test1" : {
"aliases" : { },
"mappings" : {
"properties" : {
"age" : {
"type" : "long"
},
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"settings" : {
"index" : {
"creation_date" : "1596707098264",
"number_of_shards" : "1",
"number_of_replicas" : "1",
"uuid" : "V4sVrZnuRS-ip_FHbSdupg",
"version" : {
"created" : "7080099"
},
"provided_name" : "test1"
}
}
}
}
更新索引 PUT/POST
#通过PUT覆盖更新
PUT /test1/type1/1
{
"name": "pinked",
"age": 8
}
#结果
{
"_index" : "test1",
"_type" : "type1",
"_id" : "1",
"_version" : 2, #版本号会增加
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 1
}
#通过POST修改更新
POST /test1/_update/1
{
"doc": {
"age": "9"
}
}
#结果
{
"_index" : "test1",
"_type" : "type1",
"_id" : "1",
"_version" : 3,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 2,
"_primary_term" : 1
}
删除索引 DELETE
DELETE test1
文档操作
#添加数据
PUT /pinked/user/1
{
"name": "野原新之助",
"age": 5
}
PUT /pinked/user/2
{
"name": "野比大雄",
"age": 10
}
PUT /pinked/user/3
{
"name": "胖虎",
"age": 10
}
#简单搜索
GET /pinked/user/2
#条件搜索_search?q=k:v
GET /pinked/user/_search?q=age:10
复杂查询
GET /pinked/user/_search
{
"query": {
"match": {
"name": "野"
}
},
"_source": ["name"], #选择字段
"sort": [ #排序
{
"age": {
"order": "desc"
}
}
],
"from": 0, #分页
"size": 1
}
#多条件查询
GET /pinked/user/_search
{
"query": {
"bool": {
"must": [ #must同and, should同or
{
"match": {
"name": "野"
}
},
{
"match": {
"age": 5
}
}
]
}
}
}
#
GET /pinked/user/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "野"
}
}
],
"filter": { #过滤器
"range": { #范围
"age": {
"gt": 3, #大于3
"lte": 5 #小于等于5
}
}
}
}
}
}
#结果高亮
GET /pinked/user/_search
{
"query": {
"match": {
"name": "野 大"
}
},
"highlight": {
#"pre_tags": "<span style='color:red'>", #自定义标签前缀
#"post_tags": "</span>", #自定义标签后缀
"fields": {
"name": {} #高亮的字段,会被<em>标签包裹
}
}
}
与SpringBoot整合
新建一个springboot项目
相关依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
spring data中导入的es依赖版本是7.6.2的,可以自定义导入的版本,尽量与本地的es版本保持一致
<properties>
<java.version>1.8</java.version>
<!--自定义es依赖版本至7.8.0-->
<elasticsearch.version>7.8.0</elasticsearch.version>
</properties>
配置文件
@Configuration
public class ElasticSearchClientConfig {
@Bean
public RestHighLevelClient restHighLevelClient() {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http")));
return client;
}
}
获得客户端
@Autowired
@Qualifier("restHighLevelClient")
private RestHighLevelClient client;
索引操作
//创建索引
@Test
void createIndex() throws IOException {
CreateIndexRequest request = new CreateIndexRequest("my_index");
//执行请求
CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
System.out.println(response.isAcknowledged());
}
//判断索引是否存在
@Test
void isIndexExists() throws IOException {
GetIndexRequest request = new GetIndexRequest("my_index");
boolean b = client.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(b);
}
//删除索引
@Test
void deleteIndex() throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest("my_index");
AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
System.out.println(response.isAcknowledged());
}
文档操作
//添加文档
@Test
void insertDoc() throws IOException {
User user = new User("野原新之助", 5);
IndexRequest request = new IndexRequest("my_index");
//设置规则
request.id("1")
.timeout(TimeValue.timeValueSeconds(5))
.source(JSON.toJSONString(user), XContentType.JSON);
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
System.out.println(response.toString());
System.out.println(response.status());
}
//判断文档是否存在
@Test
void isDocExists() throws IOException {
GetRequest request = new GetRequest("my_index", "1");
boolean b = client.exists(request, RequestOptions.DEFAULT);
System.out.println(b);
}
//获取文档
@Test
void getDoc() throws IOException {
GetRequest request = new GetRequest("my_index", "1");
GetResponse response = client.get(request, RequestOptions.DEFAULT);
System.out.println(response);
System.out.println(response.getSourceAsString());
}
//更新文档
@Test
void updateDoc() throws IOException {
User user = new User("野比大雄", 10);
UpdateRequest request = new UpdateRequest("my_index", "1");
request.timeout(TimeValue.timeValueSeconds(5))
.doc(JSON.toJSONString(user), XContentType.JSON);
UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
System.out.println(response.status());
}
//删除文档
@Test
void deleteDoc() throws IOException {
DeleteRequest request = new DeleteRequest("my_index", "1");
request.timeout(TimeValue.timeValueSeconds(5));
DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
System.out.println(response.status());
}
//批量操作
@Test
void BulkRequest() throws IOException {
List<User> userList = new ArrayList<>();
userList.add(new User("野原新之助", 5));
userList.add(new User("野比大雄", 10));
userList.add(new User("刚田武", 10));
BulkRequest request = new BulkRequest();
request.timeout(TimeValue.timeValueSeconds(10));
for (int i = 0; i < userList.size(); i++) {
request.add(new IndexRequest("my_index")
.id("" + i + 1)
.source(JSON.toJSONString(userList.get(i)), XContentType.JSON));
}
BulkResponse responses = client.bulk(request, RequestOptions.DEFAULT);
System.out.println(responses.hasFailures());
}
//查询
@Test
void search() throws IOException {
SearchRequest request = new SearchRequest("my_index");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
TermQueryBuilder query = QueryBuilders.termQuery("username.keyword", "野原新之助");
sourceBuilder.query(query);
sourceBuilder.timeout(TimeValue.timeValueSeconds(10));
request.source(sourceBuilder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getSourceAsString());
}
}