ElastricSearch学习记录(一)——HTTP和JavaAPI
对应课程
操作:HTTP请求
使用工具:Postman
索引和映射操作
使用PUT请求,创建索引user:
http://localhost:9200/user
使用GET请求,查看ES中所有的索引:
http://localhost:9200/_cat/indices?v
使用GET请求,查看单个索引:
http://localhost:9200/user
使用DELETE请求,删除索引:
http://localhost:9200/user
使用PUT请求,创建映射索引:
http://localhost:9200/user
{
"mappings":{
"properties":{
"name":{
"type":"text",
"index":true,
"analyzer":"ik_max_word"
},
"age":{
"type":"integer",
"index":true
},
"email":{
"type":"keyword",
"index":true
}
}
}
}
其中,"name"等表示任意起的字段名;"type"表示数据类型,对字符串而言,"text"表示可分词,"keyword"表示不可分词(数据以完整的字段进行匹配);"analyzer"为使用的分词器,"ik_max_word"为精分,"ik_smart"为粗分;"index"表示是否被索引。
使用GET请求,查看映射:
http://localhost:9200/user/_mapping
还可以向ES服务器发送PUT请求,关联索引和映射,前提是该索引并未关联其他映射:
http://localhost:9200/user/_mapping
{
"properties":{
......
}
}
文档操作
使用POST请求创建文档:
http://localhost:9200/user/_doc/{id}
+JSON请求体,如:
{
"name":"zhangsan",
"age":18,
"email":"zhangsan@163.com"
}
使用GET请求查看文档:
http://localhost:9200/user/_doc/{id}
使用POST请求修改文档:
http://localhost:9200/user/_doc/{id}
+JSON请求体,修改后_version会发生改变,使用类似“乐观锁”的控制方案。
也可通过POST请求,修改局部信息,修改后_version会发生改变:
http://localhost:9200/user/_update/{id}
{
"doc":{
"name":"zhang3"
}
}
通过DELETE请求删除文档:
http://localhost:9200/user/_doc/{id}
也可通过DELETE请求,完成条件删除:
http://localhost:9200/user/_delete_by_query
{
"query":{
"match":{
"name":"zhangsan"
}
}
}
查询操作
使用GET请求配合JSON条件查询文档:
http://localhost:9200/user/_search
或者,完成匹配查询:
+JSON请求体,如:
{
"query":{
"match":{
"name":"zhangsan"
}
}
}
完成多字段匹配查询:
{
"query":{
"multi_match":{
"name":"zhangsan",
"fields":["name","nickname"]
}
}
}
完成关键字精准查询,不对条件进行分词:
{
"query":{
"term":{
"name":"zhangsan"
}
}
}
完成多关键字精准查询:
{
"query":{
"terms":{
"name":"zhangsan",
"fields":["name","nickname"]
}
}
}
仅查询特定的字段,通过GET请求:
http://localhost:9200/user/_search
{
"_source":["name","email"],
"query":{
......
}
}
通过GET请求,完成组合查询:
“bool"组合了关键字"must”(一定满足),“must_not”(一定不满足)和"should"(不一定满足),实现组合条件查询。
{
"query":{
"bool":{
"must":[
{
"match":{
"name":"zhangsan"
}
}
],
"must_not":[
{
"match":{
"age":22
}
}
],
"should":[
{
"match":{
"email":"zhangsan@163.com"
}
}
]
}
}
}
范围查询:
{
"query":{
"range":{
"age":{
"gte":30,
"lte":35
}
}
}
}
模糊查询:fuzzy 查询会在指定的编辑距离内创建一组搜索词的所有可能的变体或扩展。然后查询返回每个扩展的完全匹配。
{
"query":{
"fuzzy":{
"name":"name"
}
}
}
排序查询,"sort"可以让我们按照不同的字段进行排序,并且通过"order"指定排序的方式。
{
"query":{
"match_all":{
}
},
"sort":[
{
"age":{
"order":"desc"
}
}
]
}
分页查询,"from"为当前页的起始索引,"size"为每页显示数据的条数。
{
"query":{
"match_all":{
}
},
"from":0,
"size":5
}
聚合查询,要结合对某个字段取"min",“max”,"sum"和"avg"的JSON对象。另外,"cardinality"表示对某个字段的值进行去重后,再取总数。
{
"aggs":{
"avg_age":{
"avg":{"field":"age"}
}
},
"size":0
}
state聚合,一次性返回count,max,min,avg 和 sum五个指标。
{
"aggs":{
"state_age":{
"stats":{
"field":"age"
}
}
}
}
分组聚合,类似SQL中的"group by",比如按年龄聚合:
{
"aggs":{
"age_groupby":{
"terms":{
"field":"age"
}
}
}
}
操作:JavaAPI
准备
工具:Springboot2.7.1+ES高级客户端+lombok+fastjson
测试工程目录:
porm.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.1</version>
</parent>
<groupId>com.jd</groupId>
<artifactId>es_test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.80</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${project.parent.version}</version>
</plugin>
</plugins>
</build>
</project>
User.java
package com.jd.es_test.pojo;
import lombok.Data;
@Data
public class User {
private String name;
private Integer age;
private String email;
}
ESConfig.java:可以没有,新版已实现配置,强迫症而已
package com.jd.es_test.conf;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ESConfig {
@Bean
public RestHighLevelClient getClient() {
return new RestHighLevelClient(RestClient.builder(HttpHost.create("http://localhost:9200")));
}
}
索引操作
EsIndexTests.java
package com.jd.es_test;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
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.client.indices.GetIndexResponse;
import org.elasticsearch.xcontent.XContentType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
@SpringBootTest
class EsIndexTests {
@Autowired
private RestHighLevelClient client;
@AfterEach
void closeClient() {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//创建索引
@Test
void createIndex() {
CreateIndexRequest request = new CreateIndexRequest("users");
try {
CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
System.out.println("响应状态:"+response.isAcknowledged());
} catch (IOException e) {
e.printStackTrace();
}
}
//获取索引
@Test
void getIndex() {
GetIndexRequest getIndexRequest = new GetIndexRequest("users");
GetIndexResponse response = null;
try {
response = client.indices().get(getIndexRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("别名:"+response.getAliases());
System.out.println("mappings:"+response.getMappings());
System.out.println("settinfs:"+response.getSettings());
}
//删除索引
@Test
void deleteIndex() {
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("users");
try {
AcknowledgedResponse response = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
System.out.println(response.isAcknowledged());
} catch (IOException e) {
e.printStackTrace();
}
}
//创建索引,并关联映射
@Test
void createIndexWithMappings() throws IOException {
CreateIndexRequest request = new CreateIndexRequest("users");
String json = "{\n" +
" \"mappings\":{\n" +
" \"properties\":{\n" +
" \"name\":{\n" +
" \"type\":\"text\",\n" +
" \"index\":true,\n" +
" \"analyzer\":\"ik_max_word\"\n" +
" },\n" +
" \"age\":{\n" +
" \"type\":\"integer\",\n" +
" \"index\":true\n" +
" },\n" +
" \"email\":{\n" +
" \"type\":\"keyword\",\n" +
" \"index\":true\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
request.source(json, XContentType.JSON);
client.indices().create(request, RequestOptions.DEFAULT);
}
}
文档操作
EsDocTests.java
package com.jd.es_test;
import com.alibaba.fastjson.JSON;
import com.jd.es_test.pojo.User;
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.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
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.common.unit.Fuzziness;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FieldAndFormat;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.xcontent.XContentType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@SpringBootTest
public class EsDocTests {
@Autowired
private RestHighLevelClient client;
@AfterEach
void closeClient() {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//批量插入
@Test
void testBulkInsert() throws IOException {
BulkRequest bulkRequest = new BulkRequest("users");
for (int i = 0; i < 11; i++) {
User user = new User();
user.setName("name"+i);
user.setAge(20+i);
user.setEmail("name"+i+"@163.com");
String json = JSON.toJSONString(user);
IndexRequest indexRequest = new IndexRequest("users").id(Integer.toString(i));
indexRequest.source(json, XContentType.JSON);
bulkRequest.add(indexRequest);
}
BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
if (bulkResponse.hasFailures()) {
System.out.println("存在失败");
} else {
System.out.println("添加成功");
}
}
//删除
@Test
void testDelete() throws IOException {
DeleteRequest deleteRequest = new DeleteRequest("users").id("10");
DeleteResponse response = client.delete(deleteRequest, RequestOptions.DEFAULT);
System.out.println(response.status());
}
//修改
@Test
void testUpdate() throws IOException {
UpdateRequest updateRequest = new UpdateRequest("users", "9");
Map<String, Object> map = new HashMap<>();
map.put("age",40);
updateRequest.doc(map);
UpdateResponse response = client.update(updateRequest, RequestOptions.DEFAULT);
System.out.println(response.status());
}
//全量搜索
@Test
void testSearchAll() throws IOException {
SearchRequest searchRequest = new SearchRequest("users");
searchRequest.source();
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
hits.forEach((hit)->{
String json = hit.getSourceAsString();
User user = JSON.parseObject(json, User.class);
System.out.println(user);
});
}
//条件搜索
@Test
void testSearchByCase() throws IOException {
SearchRequest searchRequest = new SearchRequest("users");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//添加匹配条件
sourceBuilder.query(QueryBuilders.termQuery("name","name2"));
searchRequest.source(sourceBuilder);
//查询结果
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
hits.forEach((hit)->{
String json = hit.getSourceAsString();
User user = JSON.parseObject(json, User.class);
System.out.println(user);
});
}
//分页搜索
@Test
void testSearchByPage() throws IOException {
SearchRequest searchRequest = new SearchRequest("users");
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery());
builder.from(0);
builder.size(4);
searchRequest.source(builder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
hits.forEach((hit)->{
String json = hit.getSourceAsString();
User user = JSON.parseObject(json, User.class);
System.out.println(user);
});
}
//排序搜索
@Test
void testSearchBySort() throws IOException {
SearchRequest searchRequest = new SearchRequest("users");
SearchSourceBuilder searchBuilder = new SearchSourceBuilder();
searchBuilder.sort("age", SortOrder.DESC);
searchRequest.source(searchBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
hits.forEach((hit)->{
String json = hit.getSourceAsString();
User user = JSON.parseObject(json, User.class);
System.out.println(user);
});
}
//过滤字段
@Test
void testFetch() throws IOException {
SearchRequest searchRequest = new SearchRequest("users");
SearchSourceBuilder builder = new SearchSourceBuilder();
String[] includes = {"name","email"};
String[] excludes = {};
builder.fetchSource(includes,excludes);
searchRequest.source(builder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
hits.forEach((hit)->{
String json = hit.getSourceAsString();
User user = JSON.parseObject(json, User.class);
System.out.println(user);
});
}
//多条件过滤
@Test
void testBool() throws IOException {
SearchRequest searchRequest = new SearchRequest("users");
SearchSourceBuilder builder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//一定包含
boolQueryBuilder.must(QueryBuilders.rangeQuery("age").gt(24).lt(30));
//或:可能包含
boolQueryBuilder.should(QueryBuilders.matchQuery("name","name1"));
//一定不包含
boolQueryBuilder.mustNot(QueryBuilders.matchQuery("name","name7"));
builder.query(boolQueryBuilder);
searchRequest.source(builder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
hits.forEach((hit)->{
String json = hit.getSourceAsString();
User user = JSON.parseObject(json, User.class);
System.out.println(user);
});
}
//模糊查询
@Test
void testFuzzyQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("users");
SearchSourceBuilder builder = new SearchSourceBuilder();
//模糊查询的条件:与实际数据差2个字符(多了少了都行)
QueryBuilder queryBuilder = QueryBuilders.fuzzyQuery("name","ame").fuzziness(Fuzziness.TWO);
builder.query(queryBuilder);
searchRequest.source(builder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
hits.forEach((hit)->{
String json = hit.getSourceAsString();
User user = JSON.parseObject(json, User.class);
System.out.println(user);
});
}
//分组统计
@Test
void testQuryByGroup() throws IOException {
SearchRequest searchRequest = new SearchRequest("users");
SearchSourceBuilder builder = new SearchSourceBuilder();
//分组
AggregationBuilder aggregation = AggregationBuilders.terms("age_group").field("age");
builder.aggregation(aggregation);
searchRequest.source(builder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(response);
}
}