SpringBoot?整合?ElasticSearch操作各種高級(jí)查詢搜索
一、簡(jiǎn)介
在上篇? SpringBoot 整合 ElasticSearch??? 文章中,我們?cè)敿?xì)的介紹了 ElasticSearch 的索引和文檔的基本增刪改查的操作方法!
本文將重點(diǎn)介紹 ES 的各種高級(jí)查詢寫法和使用。
廢話不多說(shuō),直接上代碼!
二、代碼實(shí)踐
本文采用的SpringBoot版本號(hào)是2.1.0.RELEASE,服務(wù)端 es 的版本號(hào)是6.8.2,客戶端采用的是官方推薦的Elastic Java High Level Rest Client版本號(hào)是6.4.2,方便與SpringBoot的版本兼容。
es 最大的亮點(diǎn)就是查詢非常豐富,可以在上億的數(shù)據(jù)里面快速搜索出目標(biāo)數(shù)據(jù),查詢?nèi)绻麑?shí)現(xiàn)呢?請(qǐng)看下文:
- 單條件精確查詢
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* 單條件精確查詢
* @throws IOException
*/
@Test
public void search0() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder()
.query(QueryBuilders.termsQuery("name", "趙里"));
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- 多條件精確查詢,取并集
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* 多條件精確查詢,取并集
* @throws IOException
*/
@Test
public void search1() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder()
.query(QueryBuilders.termsQuery("name", "張", "陳"));
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- 范圍查詢
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* 范圍查詢,包括from、to
* @throws IOException
*/
@Test
public void search2() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder()
.query(QueryBuilders.rangeQuery("age").from(20).to(32));
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
/**
* 范圍查詢,不包括from、to
* @throws IOException
*/
@Test
public void search3() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder()
.query(QueryBuilders.rangeQuery("age").from(20,false).to(30, false));
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
/**
* 范圍查詢, lt:小于,gt:大于
* @throws IOException
*/
@Test
public void search4() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder()
.query(QueryBuilders.rangeQuery("age").lt(30).gt(20));
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- 模糊查詢,支持通配符
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* 模糊查詢,支持通配符
* @throws IOException
*/
@Test
public void search5() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder()
.query(QueryBuilders.wildcardQuery("name","張三"));
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- 不使用通配符的模糊查詢,左右匹配
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* 不使用通配符的模糊查詢,左右匹配
* @throws IOException
*/
@Test
public void search6() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder()
.query(QueryBuilders.queryStringQuery("張三").field("name"));
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- 多字段模糊查詢
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* 多字段模糊查詢
* @throws IOException
*/
@Test
public void search7() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder()
.query(QueryBuilders.multiMatchQuery("長(zhǎng)", "name", "city"));
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- 多字段模糊查詢
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* 分頁(yè)搜索
* @throws IOException
*/
@Test
public void search8() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder()
.from(0).size(2);
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- 字段排序
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* 排序,字段的類型必須是:integer、double、long或者keyword
* @throws IOException
*/
@Test
public void search9() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder()
.sort("createTime", SortOrder.ASC);
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- 精確統(tǒng)計(jì)篩選文檔數(shù)
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* 精確統(tǒng)計(jì)篩選文檔數(shù),查詢性能有所降低
* @throws IOException
*/
@Test
public void search10() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder()
.trackTotalHits(true);
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- 設(shè)置源字段過(guò)濾返回
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* 設(shè)置源字段過(guò)慮,第一個(gè)參數(shù)結(jié)果集包括哪些字段,第二個(gè)參數(shù)表示結(jié)果集不包括哪些字段
* @throws IOException
*/
@Test
public void search11() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder()
.fetchSource(new String[]{"name","age","city","createTime"},new String[]{});
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- 根據(jù) id 精確匹配
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* 根據(jù)id精確匹配
* @throws IOException
*/
@Test
public void search12() throws IOException {
String[] ids = new String[]{"1","2"};
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder()
.query(QueryBuilders.termsQuery("_id", ids));
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- matchAllQuery 搜索全部
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* matchAllQuery搜索全部
* @throws IOException
*/
@Test
public void search21() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder()
.query(QueryBuilders.matchAllQuery());
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- match 搜索匹配
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* match搜索匹配
* @throws IOException
*/
@Test
public void search22() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder()
.query(QueryBuilders.matchQuery("name", "張王"));
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- bool組合查詢
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* bool組合查詢
* @throws IOException
*/
@Test
public void search23() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder();
boolQueryBuilder.must(QueryBuilders.matchQuery("name", "張王"));
boolQueryBuilder.must(QueryBuilders.rangeQuery("age").lte(30).gte(20));
builder.query(boolQueryBuilder);
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- nested 類型嵌套查詢
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* nested類型嵌套查詢
* @throws IOException
*/
@Test
public void search24() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder();
//條件查詢
BoolQueryBuilder mainBool=new BoolQueryBuilder();
mainBool.must(QueryBuilders.matchQuery("name", "趙六"));
//nested類型嵌套查詢
BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder();
boolQueryBuilder.must(QueryBuilders.matchQuery("products.brand", "A"));
boolQueryBuilder.must(QueryBuilders.matchQuery("products.title", "巧克力"));
NestedQueryBuilder nested = QueryBuilders.nestedQuery("products",boolQueryBuilder, ScoreMode.None);
mainBool.must(nested);
builder.query(mainBool);
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- 多條件查詢 + 排序 + 分頁(yè)
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* 多條件查詢 + 排序 + 分頁(yè)
* @throws IOException
*/
@Test
public void search29() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder();
//條件搜索
BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder();
boolQueryBuilder.must(QueryBuilders.matchQuery("name", "張王"));
boolQueryBuilder.must(QueryBuilders.rangeQuery("age").lte(30).gte(20));
builder.query(boolQueryBuilder);
//結(jié)果集合分頁(yè)
builder.from(0).size(2);
//排序
builder.sort("createTime",SortOrder.ASC);
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- 聚合查詢-求和
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* 聚合查詢 sum
* @throws IOException
*/
@Test
public void search30() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder();
//條件搜索
builder.query(QueryBuilders.matchAllQuery());
//聚合查詢
AggregationBuilder aggregation = AggregationBuilders.sum("sum_age").field("age");
builder.aggregation(aggregation);
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- 聚合查詢-求平均值
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* 聚合查詢 avg
* @throws IOException
*/
@Test
public void search31() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder();
//條件搜索
builder.query(QueryBuilders.matchAllQuery());
//聚合查詢
AggregationBuilder aggregation = AggregationBuilders.avg("avg_age").field("age");
builder.aggregation(aggregation);
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- 聚合查詢-計(jì)數(shù)
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* 聚合查詢 count
* @throws IOException
*/
@Test
public void search32() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder();
//條件搜索
builder.query(QueryBuilders.matchAllQuery());
//聚合查詢
AggregationBuilder aggregation = AggregationBuilders.count("count_age").field("age");
builder.aggregation(aggregation);
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}- 聚合查詢-分組
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* 聚合查詢 分組
* @throws IOException
*/
@Test
public void search33() throws IOException {
// 創(chuàng)建請(qǐng)求
SearchSourceBuilder builder = new SearchSourceBuilder();
//條件搜索
builder.query(QueryBuilders.matchAllQuery());
//聚合查詢
AggregationBuilder aggregation = AggregationBuilders.terms("tag_createTime").field("createTime")
.subAggregation(AggregationBuilders.count("count_age").field("age")) //計(jì)數(shù)
.subAggregation(AggregationBuilders.sum("sum_age").field("age")) //求和
.subAggregation(AggregationBuilders.avg("avg_age").field("age")); //求平均值
builder.aggregation(aggregation);
//不輸出原始數(shù)據(jù)
builder.size(0);
//搜索
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("cs_index");
searchRequest.types("_doc");
searchRequest.source(builder);
// 執(zhí)行請(qǐng)求
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析查詢結(jié)果
System.out.println(response.toString());
}
}三、小結(jié)
本文主要圍繞 SpringBoot 整合 ElasticSearch 進(jìn)行各種高級(jí)查詢的介紹,在下篇文章中,我們會(huì)重點(diǎn)介紹 es 的性能調(diào)優(yōu)!
到此這篇關(guān)于SpringBoot 整合 ElasticSearch操作各種高級(jí)查詢搜索的文章就介紹到這了,更多相關(guān)SpringBoot 整合 ES 查詢搜索內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springmvc用于方法鑒權(quán)的注解攔截器的解決方案代碼
這篇文章主要介紹了springmvc用于方法鑒權(quán)的注解攔截器的解決方案代碼,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12
Spring Boot教程之利用ActiveMQ實(shí)現(xiàn)延遲消息
這篇文章主要給大家介紹了關(guān)于Spring Boot教程之利用ActiveMQ實(shí)現(xiàn)延遲消息的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
Spring?Boot項(xiàng)目集成Knife4j接口文檔的實(shí)例代碼
Knife4j就相當(dāng)于是swagger的升級(jí)版,對(duì)于我來(lái)說(shuō),它比swagger要好用得多<BR>,這篇文章主要介紹了Spring?Boot項(xiàng)目集成Knife4j接口文檔的示例代碼,需要的朋友可以參考下2021-12-12
自定義spring mvc的json視圖實(shí)現(xiàn)思路解析
這篇文章主要介紹了自定義spring mvc的json視圖的實(shí)現(xiàn)思路解析,本文給大家介紹的非常詳細(xì),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-12-12
Spring中@PropertySource注解使用場(chǎng)景解析
這篇文章主要介紹了Spring中@PropertySource注解使用場(chǎng)景解析,@PropertySource注解就是Spring中提供的一個(gè)可以加載配置文件的注解,并且可以將配置文件中的內(nèi)容存放到Spring的環(huán)境變量中,需要的朋友可以參考下2023-11-11
使用Java獲取List交集數(shù)據(jù)的實(shí)現(xiàn)方案小結(jié)
今天遇到一個(gè)小需求,當(dāng)用戶上傳了一個(gè)關(guān)于用戶數(shù)據(jù)的列表,我們需要將其與數(shù)據(jù)庫(kù)中已有的用戶數(shù)據(jù)進(jìn)行比較,所以本文給大家介紹了使用Java獲取List交集數(shù)據(jù)的實(shí)現(xiàn)方案小結(jié),文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下2024-03-03

