SpringBoot?整合?ElasticSearch操作各種高級(jí)查詢搜索
一、簡(jiǎn)介
在上篇? SpringBoot 整合 ElasticSearch??? 文章中,我們?cè)敿?xì)的介紹了 ElasticSearch 的索引和文檔的基本增刪改查的操作方法!
本文將重點(diǎn)介紹 ES 的各種高級(jí)查詢寫法和使用。
廢話不多說,直接上代碼!
二、代碼實(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;
/**
* 分頁搜索
* @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è)置源字段過濾返回
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* 設(shè)置源字段過慮,第一個(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());
}
}- 多條件查詢 + 排序 + 分頁
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {
@Autowired
private RestHighLevelClient client;
/**
* 多條件查詢 + 排序 + 分頁
* @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é)果集合分頁
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)文章
Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(28)
下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望可以幫到你2021-07-07
SpringBoot2.3.0配置JPA的實(shí)現(xiàn)示例
這篇文章主要介紹了SpringBoot2.3.0配置JPA的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
spring的data派生查詢機(jī)制的實(shí)現(xiàn)
SpringData的派生查詢是一種通過方法名約定自動(dòng)生成數(shù)據(jù)庫查詢的機(jī)制,無需手動(dòng)編寫SQL或JPQL,下面就來介紹一下spring data派生查詢的實(shí)現(xiàn),感興趣的可以了解一下2025-03-03
Java的動(dòng)態(tài)綁定與雙分派_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了Java的動(dòng)態(tài)綁定與雙分派,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08
詳解Java對(duì)象創(chuàng)建的過程及內(nèi)存布局
今天給大家?guī)淼奈恼率荍ava對(duì)象創(chuàng)建的過程及內(nèi)存布局,文中有非常詳細(xì)的圖文示例及介紹,需要的朋友可以參考下2021-06-06
Java中的clone方法詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
clone顧名思義就是復(fù)制, 在Java語言中, clone方法被對(duì)象調(diào)用,所以會(huì)復(fù)制對(duì)象。下面通過本文給大家介紹java中的clone方法,感興趣的朋友一起看看吧2017-06-06
java實(shí)現(xiàn)解析json復(fù)雜數(shù)據(jù)的方法詳解
這篇文章主要為大家詳細(xì)介紹了java如何實(shí)現(xiàn)解析json復(fù)雜數(shù)據(jù),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以學(xué)習(xí)一下2024-01-01

