日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

SpringBoot整合elasticsearch (java整合es)

發布時間:2024/1/8 javascript 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpringBoot整合elasticsearch (java整合es) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

歡迎大家進群,一起探討學習

微信公眾號,每天給大家提供技術干貨

博主技術筆記

博主網站地址1

博主網站地址2


博主開源微服架構前后端分離技術博客項目源碼地址,歡迎各位star


SpringBoot整合elasticsearch

pom引入

<!--elasticsearch--><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.5.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.6</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.47</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></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></dependency>

yml配置

spring:data:elasticsearch:rest:uris: ["ip:9200"]elasticsearch:cluster-name: docker-clustercluster-nodes: ip:9300 #配置es節點信息,逗號分隔,如果沒有指定,則啟動ClientNodeproperties:path:logs: ./elasticsearch/log #elasticsearch日志存儲目錄data: ./elasticsearch/data #elasticsearch數據存儲目錄

配置只需這么些,接下來就寫一些demo來玩一下elaseticsearch

構建Item類

@Document(indexName = "item",type = "docs", shards = 1, replicas = 0) public class Item {@Idprivate Long id;//文章使用分詞器@Field(type = FieldType.Text, analyzer = "ik_max_word")private String title; //標題@Field(type = FieldType.Keyword)private String category;// 分類@Field(type = FieldType.Keyword)private String brand; // 品牌@Field(type = FieldType.Double)private Double price; // 價格}

創建ItemRepository并繼承ElasticsearchRepository,有興趣的可以看一下底層源碼

public interface ItemRepository extends ElasticsearchRepository<Item,Long>{/*** @Description:根據價格區間查詢 自定義查詢* @Param price1* @Param price2*/List<Item> findByPriceBetween(double price1, double price2);List<Item> findByTitle(String title1);List<Item> findByTitleIn(Collection<String> ss); }

創建索引

@RunWith(SpringRunner.class) @SpringBootTest(classes = BootApplication.class) public class EsDemoApplicationTest{@Autowiredprivate ElasticsearchRestTemplate elasticsearchRestTemplate;/*** @Description:創建索引,會根據Item類的@Document注解信息來創建*/@Testpublic void testCreateIndex() {elasticsearchRestTemplate.indexOps(Item.class).create();}/*** @Description:刪除索引*/@Testpublic void testDeleteIndex() {elasticsearchRestTemplate.indexOps(Item.class).delete();}/*** @Description:判斷索引是否存在*/@Testpublic void testExistIndex() {elasticsearchRestTemplate.indexOps(Item.class).exists();}/*** @Description:刪除*/@Testpublic void delete() {elasticsearchRestTemplate.delete(1L, Item.class);}/*** 查詢文檔數據*/@Testpublic void getDoc() {Item item = elasticsearchRestTemplate.get(String.valueOf(1L), Item.class);System.out.println(item);}/*** 修改文檔數據*/@Testpublic void updateDoc() {Map<String, Object> map = new HashMap<>();map.put("title", "abc");Document doc = Document.from(map);UpdateQuery updateQuery = UpdateQuery.builder(String.valueOf(1)).withDocument(doc).build();IndexCoordinates indexCoordinates = IndexCoordinates.of("item");elasticsearchRestTemplate.update(updateQuery, indexCoordinates);}/*** 分頁搜索數據* 使用QueryBuilder* termQuery("key", obj) 完全匹配* termsQuery("key", obj1, obj2..) 一次匹配多個值* matchQuery("key", Obj) 單個匹配, field不支持通配符, 前綴具高級特性* multiMatchQuery("text", "field1", "field2"..); 匹配多個字段, field有通配符忒行* matchAllQuery(); 匹配所有文件* idsQuery(); 只查詢一個id的* fuzzyQuery(); 模糊查詢 不能用通配符, 找到相似的*/@Testpublic void search() {Pageable pageable = PageRequest.of(0, 10);SortBuilder<FieldSortBuilder> sortBuilder = new FieldSortBuilder("price").order(SortOrder.DESC);NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(QueryBuilders.boolQuery().should(QueryBuilders.fuzzyQuery("title", "360"))).withPageable(pageable).withSort(sortBuilder).build();SearchHits<Item> search = elasticsearchRestTemplate.search(query, Item.class);System.out.println(search.getSearchHits());}/*** 高亮搜索*/@Testpublic void highlight() {String preTag = "<font color='red'>";String postTag = "</font>";NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery("title", "360")).withHighlightFields(new HighlightBuilder.Field("title").preTags(preTag).postTags(postTag)).build();SearchHits<Item> searchHits = elasticsearchRestTemplate.search(query, Item.class);List<SearchHit<Item>> searchHitList = searchHits.getSearchHits();List<Map<String, Object>> hlList = new ArrayList<>();for (SearchHit h : searchHitList) {List<String> highlightField = h.getHighlightField("title");String nameValue = highlightField.get(0);String originalJson = JSON.toJSONString(h.getContent());JsonParser jj = new GsonJsonParser();Map<String, Object> myHighLight = jj.parseMap(originalJson);// 用高亮的搜索結果覆蓋原字段值myHighLight.put("title", nameValue);System.out.println(myHighLight);hlList.add(myHighLight);}System.out.println(hlList);}/*** 高亮搜索 排序加分頁*/@Testpublic void highlight1() {String preTag = "<font color='red'>";String postTag = "</font>";Pageable pageable = PageRequest.of(0, 10);SortBuilder<FieldSortBuilder> sortBuilder = new FieldSortBuilder("price").order(SortOrder.DESC);NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(QueryBuilders.fuzzyQuery("title", "360")).withPageable(pageable).withSort(sortBuilder).withHighlightFields(new HighlightBuilder.Field("title").preTags(preTag).postTags(postTag)).build();SearchHits<Item> searchHits = elasticsearchRestTemplate.search(query, Item.class);List<SearchHit<Item>> searchHitList = searchHits.getSearchHits();List<Map<String, Object>> hlList = new ArrayList<>();for (SearchHit h : searchHitList) {List<String> highlightField = h.getHighlightField("title");String nameValue = highlightField.get(0);String originalJson = JSON.toJSONString(h.getContent());JsonParser jj = new GsonJsonParser();Map<String, Object> myHighLight = jj.parseMap(originalJson);// 用高亮的搜索結果覆蓋原字段值myHighLight.put("title", nameValue);hlList.add(myHighLight);}System.out.println(hlList);} }

QueryBuilder構造ES查詢條件使用規則

https://blog.csdn.net/csdn_20150804/article/details/105618933

第二種實現方式 RestHighLevelClient

package comn.hy.search.service.impl;import com.hy.search.Stu; import com.hy.utils.JsonUtils; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; 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.get.GetRequest; import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.support.master.AcknowledgedResponse; 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.client.indices.CreateIndexRequest; import org.elasticsearch.client.indices.CreateIndexResponse; import org.elasticsearch.client.indices.GetIndexRequest; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.TermQueryBuilder; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.fetch.subphase.FetchSourceContext; import org.springframework.web.bind.annotation.*;import javax.annotation.Resource; import java.io.IOException; import java.util.ArrayList; import java.util.concurrent.TimeUnit; @RestController public class TestServiceES {@Resourceprivate RestHighLevelClient client;/*** 創建索引* @throws IOException*/@PostMapping("create-index")public void createIndex() throws IOException {CreateIndexRequest request = new CreateIndexRequest("user_index");CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);System.out.println(response);}/*** 獲取索引信息* @throws IOException*/@GetMapping("query-index")public void queryIndex() throws IOException {GetIndexRequest request = new GetIndexRequest("user_index");boolean b = client.indices().exists(request, RequestOptions.DEFAULT);System.out.println(b);}/*** 刪除索引* @throws IOException*/@DeleteMapping("delete-index")public void deleteIndex() throws IOException {DeleteIndexRequest request = new DeleteIndexRequest("user_index");AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);System.out.println(delete.isAcknowledged());}/*** 新增一個文檔* @throws IOException*/@PostMapping("add-doc")public void addDoc() throws IOException {Stu stu = new Stu(10010L, "絕世風華", 18, 100.5f, true);IndexRequest request = new IndexRequest("user_index");// 規則 put /test_index/_doc/1request.id("1");request.timeout(new TimeValue(60, TimeUnit.SECONDS));request.source(JsonUtils.objectToJson(stu),XContentType.JSON);// 發送IndexResponse response = client.index(request,RequestOptions.DEFAULT);System.out.println(response.toString());System.out.println(response.status());}/*** 查詢文檔數據* @throws IOException*/@GetMapping("query-doc")void queryDoc() throws IOException {GetRequest request = new GetRequest("user_index","1");request.fetchSourceContext(new FetchSourceContext(false));request.storedFields("_none_");// 是否存在???boolean b = client.exists(request,RequestOptions.DEFAULT);System.out.println(b);// 獲取GetResponse response = client.get(request,RequestOptions.DEFAULT);System.out.println(response.getSourceAsString());System.out.println(response);}/*** 更新文檔* @throws IOException*/@PutMapping("update-doc")public void updateDoc() throws IOException {UpdateRequest updateRequest = new UpdateRequest("user_index","1");updateRequest.timeout("1s");Stu stu = new Stu(10010L, "上善若水", 18, 100.5f, true);updateRequest.doc(JsonUtils.objectToJson(stu),XContentType.JSON);UpdateResponse response = client.update(updateRequest,RequestOptions.DEFAULT);System.out.println(response);System.out.println(response.status());}/*** 刪除文檔* @throws IOException*/@DeleteMapping("delete-doc")public void deleteDoc() throws IOException {DeleteRequest deleteRequest = new DeleteRequest("user_index","1");deleteRequest.timeout("1s");DeleteResponse response = client.delete(deleteRequest,RequestOptions.DEFAULT);System.out.println(response);System.out.println(response.status());}/*** 批量操作* @throws IOException*/@PostMapping("bulk-operator")public void bulkOperator() throws IOException {BulkRequest bulkRequest = new BulkRequest();bulkRequest.timeout("15s");Stu stu0 = new Stu(10010L, "諸天萬界之起源傳說", 18, 100.5f, true);Stu stu1 = new Stu(10011L, "寒夜", 20, 88.5f, true);Stu stu2 = new Stu(10012L, "陌上千尋雪", 22, 96.5f, false);Stu stu3 = new Stu(10013L, "可愛的漂亮的小哥哥", 26, 108.5f, false);Stu stu4 = new Stu(10014L, "靈紀傳說", 28, 108.6f, true);Stu stu5 = new Stu(10015L, "狂劍天下之鴻蒙掌控", 16, 18.5f, false);Stu stu6 = new Stu(10016L, "逆戰次元", 29, 100.5f, true);ArrayList<Stu> stuList = new ArrayList<>();stuList.add(stu0);stuList.add(stu1);stuList.add(stu2);stuList.add(stu3);stuList.add(stu4);stuList.add(stu5);stuList.add(stu6);for(int i = 0;i<=stuList.size();i++){bulkRequest.add(new IndexRequest("test.index").id(""+(i+1)).source(JsonUtils.objectToJson(stuList.get(i)), XContentType.JSON));}// 批量插入BulkResponse response = client.bulk(bulkRequest,RequestOptions.DEFAULT);System.out.println(response.hasFailures());}/*** 條件查詢* @throws IOException*/@GetMapping("condition-search")public void conditionSearch() throws IOException {SearchRequest searchRequest = new SearchRequest("user_index");// 構造條件SearchSourceBuilder builder = new SearchSourceBuilder();// 精確匹配TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name","絕世風華");// 匹配全部 matchAllQuery();builder.query(termQueryBuilder);// 分頁builder.from(0);builder.size(10);builder.timeout(TimeValue.MINUS_ONE);searchRequest.source(builder);SearchResponse response = client.search(searchRequest,RequestOptions.DEFAULT);System.out.println(JsonUtils.objectToJson(response.getHits()));for (org.elasticsearch.search.SearchHit hit : response.getHits().getHits()) {hit.getSourceAsMap().get("name");}}}

先執行創建索引
索引數據操作

@RunWith(SpringRunner.class) @SpringBootTest(classes = BootApplication.class) public class ceshiTest {@Autowiredprivate ItemRepository itemRepository;/*** @Description:定義新增方法*/@Testpublic void insert() {Item item = new Item(1L, "小米手機7", " 手機","小米", 3499.00);itemRepository.save(item);}/*** @Description:定義批量新增方法*/@Testpublic void insertList() {List<Item> list = new ArrayList<>();list.add(new Item(1L, "小米9", "手機", "小米", 3299.00));list.add(new Item(2L, "華為pro30", "手機", "華為", 3999.00));list.add(new Item(3L, "一加7", "手機", "一加", 2999.00));list.add(new Item(4L, "魅族16", "手機", "魅族", 1999.00));list.add(new Item(5L, "蘋果xs", "手機", "蘋果", 5099.00));list.add(new Item(6L, "360pro", "手機", "360", 1099.00));list.add(new Item(7L, "榮耀V10", "手機", "華為", 899.00 ));// 接收對象集合,實現批量新增itemRepository.save(list);}/*** @Description:按照價格區間查詢 自定義方法* 自定義方法Spring Data 的另一個強大功能,是根據方法名稱自動實現功能。比如:你的方法名叫做:findByTitle,那么它就知道你是根據title查詢,然后自動幫你完成,無需寫實現類。當然,方法名稱要符合一定的約定 下邊為約定And findByNameAndPriceOr findByNameOrPriceIs findByNameNot findByNameNotBetween findByPriceBetweenLessThanEqual findByPriceLessThanGreaterThanEqual findByPriceGreaterThanBefore findByPriceBeforeAfter findByPriceAfterLike findByNameLikeStartingWith findByNameStartingWithEndingWith findByNameEndingWithContains/Containing findByNameContainingIn findByNameIn(Collection<String>names)NotIn findByNameNotIn(Collection<String>names)Near findByStoreNearTrue findByAvailableTrueFalse findByAvailableFalseOrderBy findByAvailableTrueOrderByNameDesc* @Author: https://blog.csdn.net/chen_2890*/@Testpublic void queryByPriceBetween(){List<Item> list = this.itemRepository.findByPriceBetween(2000.00, 3500.00);for (Item item : list) {System.out.println("item = " + item.getTitle());}}@Testpublic void queryByTitle(){List<Item> list = this.itemRepository.findByTitle("華為");for (Item item : list) {System.out.println("item = " + item.getTitle());}}@Testpublic void queryByTitleTo(){Collection<String> ss = new ArrayList<>();ss.add("華為");ss.add("小米");List<Item> list = this.itemRepository.findByTitleIn(ss);for (Item item : list) {System.out.println("item = " + item.getTitle());}}/*** @Description:matchQuery底層采用的是詞條匹配查詢* @Author: https://blog.csdn.net/chen_2890*/@Testpublic void testMatchQuery(){// 構建查詢條件NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();// 添加基本分詞查詢queryBuilder.withQuery(QueryBuilders.matchQuery("title", "華為"));// 搜索,獲取結果Page<Item> items = this.itemRepository.search(queryBuilder.build());// 總條數long total = items.getTotalElements();System.out.println("獲取的總條數 = " + total);for (Item item : items) {System.out.println("手機名稱是:"+item.getTitle());}}/*** @Description:* termQuery:功能更強大,除了匹配字符串以外,還可以匹配* int/long/double/float/....* @Author: https://blog.csdn.net/chen_2890*/@Testpublic void testTermQuery(){NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();builder.withQuery(QueryBuilders.termQuery("price",1099));// 查找Page<Item> page = this.itemRepository.search(builder.build());for(Item item:page){System.out.println("手機是:"+item.getTitle());}}/*** @Description:布爾查詢 多條件查詢* @Author: https://blog.csdn.net/chen_2890*/@Testpublic void testBooleanQuery(){NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();builder.withQuery(QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("title","華為")).must(QueryBuilders.matchQuery("brand","華為")));// 查找Page<Item> page = this.itemRepository.search(builder.build());for(Item item:page){System.out.println("手機名稱是"+item.getTitle());}}/*** @Description:布爾查詢 多條件查詢* @Author: https://blog.csdn.net/chen_2890*/@Testpublic void testBlQuery(){NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();builder.withQuery(QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("title","榮耀")).must(QueryBuilders.matchQuery("title","華為")));// 查找Page<Item> page = this.itemRepository.search(builder.build());for(Item item:page){System.out.println("手機名稱是"+item.getTitle());}}/*** @Description:模糊查詢* @Author: https://blog.csdn.net/chen_2890*/@Testpublic void testFuzzyQuery(){NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();builder.withQuery(QueryBuilders.fuzzyQuery("title","一"));Page<Item> page = this.itemRepository.search(builder.build());for(Item item:page){System.out.println("手機名稱是:"+item.getTitle());}}/*** @Description:分頁查詢* @Author: https://blog.csdn.net/chen_2890*/@Testpublic void searchByPage(){// 構建查詢條件NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();// 添加基本分詞查詢queryBuilder.withQuery(QueryBuilders.termQuery("category", "手機"));// 分頁:int page = 0;int size = 2;queryBuilder.withPageable(PageRequest.of(page,size));// 搜索,獲取結果Page<Item> items = this.itemRepository.search(queryBuilder.build());// 總條數long total = items.getTotalElements();System.out.println("總條數 = " + total);// 總頁數System.out.println("總頁數 = " + items.getTotalPages());// 當前頁System.out.println("當前頁:" + items.getNumber());// 每頁大小System.out.println("每頁大小:" + items.getSize());for (Item item : items) {System.out.println(item.getTitle());}}/*** @Description:排序查詢* @Author: https://blog.csdn.net/chen_2890*/@Testpublic void searchAndSort(){// 構建查詢條件NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();// 添加基本分詞查詢queryBuilder.withQuery(QueryBuilders.termQuery("category", "手機"));// 排序queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC));// 搜索,獲取結果Page<Item> items = this.itemRepository.search(queryBuilder.build());// 總條數long total = items.getTotalElements();System.out.println("總條數 = " + total);for (Item item : items) {System.out.println("手機的價格是:"+item.getTitle()+":"+item.getPrice());}}/*** @Description:按照品牌brand進行分組* @Author: https://blog.csdn.net/chen_2890*/@Testpublic void testAgg(){NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();// 不查詢任何結果queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));// 1、添加一個新的聚合,聚合類型為terms,聚合名稱為brands,聚合字段為brandqueryBuilder.addAggregation(AggregationBuilders.terms("brands").field("brand"));// 2、查詢,需要把結果強轉為AggregatedPage類型AggregatedPage<Item> aggPage = (AggregatedPage<Item>) this.itemRepository.search(queryBuilder.build());// 3、解析// 3.1、從結果中取出名為brands的那個聚合,// 因為是利用String類型字段來進行的term聚合,所以結果要強轉為StringTerm類型StringTerms agg = (StringTerms) aggPage.getAggregation("brands");// 3.2、獲取桶List<StringTerms.Bucket> buckets = agg.getBuckets();// 3.3、遍歷for (StringTerms.Bucket bucket : buckets) {// 3.4、獲取桶中的key,即品牌名稱System.out.println(bucket.getKeyAsString());// 3.5、獲取桶中的文檔數量System.out.println(bucket.getDocCount());}}/*** @Description:嵌套聚合,求平均值* @Author: https://blog.csdn.net/chen_2890*/@Testpublic void testSubAgg(){NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();// 不查詢任何結果queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));// 1、添加一個新的聚合,聚合類型為terms,聚合名稱為brands,聚合字段為brandqueryBuilder.addAggregation(AggregationBuilders.terms("brands").field("brand").subAggregation(AggregationBuilders.avg("priceAvg").field("price")) // 在品牌聚合桶內進行嵌套聚合,求平均值);// 2、查詢,需要把結果強轉為AggregatedPage類型AggregatedPage<Item> aggPage = (AggregatedPage<Item>) this.itemRepository.search(queryBuilder.build());// 3、解析// 3.1、從結果中取出名為brands的那個聚合,// 因為是利用String類型字段來進行的term聚合,所以結果要強轉為StringTerm類型StringTerms agg = (StringTerms) aggPage.getAggregation("brands");// 3.2、獲取桶List<StringTerms.Bucket> buckets = agg.getBuckets();// 3.3、遍歷for (StringTerms.Bucket bucket : buckets) {// 3.4、獲取桶中的key,即品牌名稱 3.5、獲取桶中的文檔數量System.out.println(bucket.getKeyAsString() + ",共" + bucket.getDocCount() + "臺");// 3.6.獲取子聚合結果:InternalAvg avg = (InternalAvg) bucket.getAggregations().asMap().get("priceAvg");System.out.println("平均售價:" + avg.getValue());}} }

總結

以上是生活随笔為你收集整理的SpringBoot整合elasticsearch (java整合es)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。