一、认识ES
二、ES相关安装和部署(elasticsearch 、kbana、ik)
这部分的内容可以查看我之前写的Docker常用部署这篇文章
三、Mapping映射
3.1 Mapping映射属性
3.2 索引库操作
3.2.1 遵循Restful规范说明
3.2.2 具体使用方式说明
3.2.3增删改查示例
#创建
PUT /heima
{
"mappings":{
"properties": {
"info":{
"type": "text",
"analyzer": "ik_smart"
},
"email": {
"type": "keyword",
"index": false
},
"name": {
"type": "object",
"properties": {
"firstName":{
"type": "keyword"
},
"lastName": {
"type": "keyword"
}
}
}
}
}
}
#查询
GET /heima
#删除
DELETE /heima
#添加
PUT /heima/_mapping
{
"properties":{
"age":{
"type":"byte"
}
}
}
3.2.4 总结
3.3 文档的操作
3.3.1 文档的增删改查示例
#新增文档(如果已经存在则进行修改)
POST /heima/_doc/1
{
"info": "Java入门到精通",
"email": "csh@qq.com",
"name": {
"firstName": "云",
"lastName": "赵"
}
}
#查询文档
GET /heima/_doc/1
#删除文档
DELETE /heima/_doc/1
#全量修改(直接覆盖之前的文档,如果不存在该文档则会创建新的文档)
PUT /heima/_doc/1
{
"info": "Python入门到精通",
"email": "csh@163.com",
"name": {
"firstName": "白",
"lastName": "李"
}
}
#增量修改(局部修改)
POST /heima/_update/1
{
"doc":{
"email":"333@163.com"
}
}
3.3.2 文档批量处理
#批量添加
POST /_bulk
{"index": {"_index" : "heima" , "_id":1}}
{"info":"Java入门到精通","email":"csh@qq.com","name":{"firstName": "云","lastName": "赵"}}
{"index": {"_index" : "heima" , "_id":2}}
{"info":"Python入门到精通","email":"csh@163.com","name":{"firstName": "白","lastName": "李"}}
#批量删除
POST /heima/_bulk
{"delete": {"_index" : "heima" , "_id":1}}
{"delete": {"_index" : "heima" , "_id":2}}
3.3.3 总结
四、JavaRestClient(索引库)
4.1 客户端初始化
第一步:
引入依赖:
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
第二步:
在Spring-boot-dependency中找出<elaticsearch.version>7.17.0</elaticsearch.version>,
将其复制在父工程的<properties></properties>中修改版本号好为7.12.1(可根据自己所需要的版本进行修改)
第三步:通过RestHighLevelClient使用ES
建立ES连接示例:
package com.etc.search;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
@SpringBootTest
class TripSearchApplicationTests {
private RestHighLevelClient client;
@Test
void testConnection() {
System.out.println("client: "+client);
}
@BeforeEach
void setUp(){
client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.92.136:9200")
));
}
@AfterEach
void tearDown() throws IOException{
if(client != null){
client.close();
}
}
}
4.2 商品映射Mapping
kibana创建示例:
PUT /item
{
"mappings": {
"properties": {
"id":{
"type": "keyword"
},
"name":{
"type": "text",
"analyzer": "ik_smart"
},
"price":{
"type": "integer"
},
"image":{
"type": "keyword",
"index": false
},
"category":{
"type":"keyword"
},
"brand":{
"type": "keyword"
},
"sold":{
"type": "integer"
},
"commentCount":{
"type": "integer",
"index": false
},
"isAD":{
"type": "boolean"
},
"updateTime":{
"type": "date"
}
}
}
}
4.3 使用Java客户端示例:
package com.etc.search;
import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.web.bind.annotation.DeleteMapping;
import java.io.IOException;
@SpringBootTest
class TripSearchApplicationTests {
private RestHighLevelClient client;
@Test
void testConnection() {
System.out.println("client: "+client);
}
@Test
void testCreateIndex() throws IOException{
CreateIndexRequest request = new CreateIndexRequest("items");
request.source(MAPPING_TEMPLATE, XContentType.JSON);
client.indices().create(request, RequestOptions.DEFAULT);
}
@Test
void testGetIndex() throws IOException{
GetIndexRequest request = new GetIndexRequest("items");
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
System.out.println("exists:"+exists);
}
@Test
void testDeleteIndex() throws IOException{
DeleteIndexRequest request = new DeleteIndexRequest("items");
client.indices().delete(request, RequestOptions.DEFAULT);
}
@BeforeEach
void setUp(){
client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.92.136:9200")
));
}
@AfterEach
void tearDown() throws IOException{
if(client != null){
client.close();
}
}
private static final String MAPPING_TEMPLATE = "{\n" +
" \"mappings\": {\n" +
" \"properties\": {\n" +
" \"id\":{\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"name\":{\n" +
" \"type\": \"text\",\n" +
" \"analyzer\": \"ik_smart\"\n" +
" },\n" +
" \"price\":{\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"image\":{\n" +
" \"type\": \"keyword\",\n" +
" \"index\": false\n" +
" },\n" +
" \"category\":{\n" +
" \"type\":\"keyword\"\n" +
" },\n" +
" \"brand\":{\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"sold\":{\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"commentCount\":{\n" +
" \"type\": \"integer\",\n" +
" \"index\": false\n" +
" },\n" +
" \"isAD\":{\n" +
" \"type\": \"boolean\"\n" +
" },\n" +
" \"updateTime\":{\n" +
" \"type\": \"date\"\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
}
4.4 总结
五、JavaRestClient(文档)
5.1 使用Java客户端示例:
示例代码:
package com.etc.search;
import org.apache.http.HttpHost;
import org.bouncycastle.cert.ocsp.Req;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
@SpringBootTest
class TripSearchApplicationTests {
private RestHighLevelClient client;
@Test
void testConnection() {
System.out.println("client: "+client);
}
private static final String DOCUMENT_TEMPLATE = "{\n" +
" \"id\":\"1\",\n" +
" \"name\":\"csh\",\n" +
" \"price\":\"11\"\n" +
"}";
@Test
void testCreateDocument() throws IOException{
IndexRequest request = new IndexRequest("items").id("1");
request.source(DOCUMENT_TEMPLATE,XContentType.JSON);
client.index(request,RequestOptions.DEFAULT);
}
@Test
void testDeleteDocument() throws IOException{
DeleteRequest request = new DeleteRequest("items","1");
client.delete(request,RequestOptions.DEFAULT);
}
@Test
void testGetDocument() throws IOException{
GetRequest request = new GetRequest("items","1");
GetResponse response = client.get(request, RequestOptions.DEFAULT);
String json = response.getSourceAsString();
System.out.println(json);
}
@Test
void testUpdateDocument() throws IOException{
UpdateRequest request = new UpdateRequest("items","1");
request.doc(
"name","csh2024",
"price",2024
);
client.update(request,RequestOptions.DEFAULT);
}
@BeforeEach
void setUp(){
client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.92.136:9200")
));
}
@AfterEach
void tearDown() throws IOException{
if(client != null){
client.close();
}
}
}
5.2 文档批量操作
5.3 总结:
六、DSL查询
6.1 DSL查询介绍
6.2 DSL查询所有
6.3 DSL叶子查询
match查询单个字段,需要更改key和value的值,而multi_match查询多个字段,key值无需改变。
6.4 复合查询
6.4.1 复合查询的bool查询
6.4.2 复合查询的排序和分页
示例:先按照销量降序排列,若销量一直则按升序排列
GET /items/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"sold": {
"order": "desc"
},
"price": {
"order": "asc"
}
}
]
}
from的计算公式:(页数-1)*页条;
ES对from和size进行限制,两者相加不能超过10000
6.5 高亮
6.6 搜索总结
七、JavaRestClient (搜索)
7.1 查询所有
示例:查询所有(match_all)
package com.etc.search;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
@SpringBootTest
class TripSearchApplicationTests {
private RestHighLevelClient client;
@Test
void testMatchAll() throws IOException{
SearchRequest request = new SearchRequest("items");
request.source()
.query(QueryBuilders.matchAllQuery());
SearchResponse response = client.search(request,RequestOptions.DEFAULT);
System.out.println("response = "+ response);
}
@BeforeEach
void setUp(){
client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.92.136:9200")
));
}
@AfterEach
void tearDown() throws IOException{
if(client != null){
client.close();
}
}
}
7.2 解析查询结果
7.3 构建查询条件
7.3.1 构建查询条件(matchQuery,multiMatchQuery)
7.3.2 构建查询条件(termQuery,rangeQuery)
7.3.3 构建查询条件(bool查询)
示例:使用JavaRestClient实现以下的搜索:
- 搜索关键字为脱脂牛奶
- 品牌为德亚
- 价格必须低于300
代码:
package com.etc.search;
import net.minidev.json.JSONUtil;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
@SpringBootTest
class TripSearchApplicationTests {
private RestHighLevelClient client;
@Test
void testSearch() throws IOException{
SearchRequest request = new SearchRequest("items");
request.source()
.query(QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("name","脱脂牛奶"))
.filter(QueryBuilders.termQuery("brand","德亚"))
.filter(QueryBuilders.rangeQuery("price").lt(300)));
SearchResponse response = client.search(request,RequestOptions.DEFAULT);
parseResponseResult(response);
}
private static void parseResponseResult(SearchResponse response) {
//总条数
SearchHits searchHits = response.getHits();
long total = searchHits.getTotalHits().value;
System.out.println("total = "+total);
//命中条数
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit: hits){
String json = hit.getSourceAsString();
System.out.println("doc = "+ json);
}
}
@BeforeEach
void setUp(){
client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.92.136:9200")
));
}
@AfterEach
void tearDown() throws IOException{
if(client != null){
client.close();
}
}
}
7.3.4 排序和分页
7.4 高亮
高亮显示结果解析
示例:解析结果方法
private static void parseResponseResult(SearchResponse response) {
//总条数
SearchHits searchHits = response.getHits();
long total = searchHits.getTotalHits().value;
System.out.println("total = "+total);
//命中条数
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit: hits){
String json = hit.getSourceAsString();
//转换为ItemDoc
ItemDoc doc = JSONUtil.toBean(json,ItemDoc.class);
//处理高亮结果
Map<String, HighlightField> hfs = hit.getHighlightFields();
if(hfs != null && !hfs.isEmpty()){
HighlightField hf = hfs.get("name");
String hfName = hf.getFragments()[0].string();
doc.setName(hfName);
}
System.out.println("doc = "+ doc);
}
}
八、数据聚合
8.1 数据聚合的介绍
注意:参与聚合的字段必须是Keyword、数值、日期、布尔类型的字段
8.2 DSL聚合
8.3 JavaRestClient数据聚合
package com.etc.search;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@SpringBootTest
class TripSearchApplicationTests {
private RestHighLevelClient client;
@Test
void testAgg() throws IOException{
SearchRequest request = new SearchRequest("items");
request.source().size(0);
String brandAggName = "brandAgg";
request.source().aggregation(
AggregationBuilders.terms(brandAggName).field("brand").size(10)
);
SearchResponse response = client.search(request,RequestOptions.DEFAULT);
Aggregations aggregations = response.getAggregations();
Terms brandTerms = aggregations.get(brandAggName);
List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
for (Terms.Bucket bucket :buckets){
System.out.println("brand: "+bucket.getKeyAsString());
System.out.println("count: "+bucket.getDocCount());
}
}
@BeforeEach
void setUp(){
client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.92.136:9200")
));
}
@AfterEach
void tearDown() throws IOException{
if(client != null){
client.close();
}
}
}