SpringBoot 3.2.5 + ElasticSearch 8.12.0 - SpringData 開發指南

?

目錄

一、SpringData ElasticSearch

1.1、環境配置

1.2、創建實體類

1.3、ElasticSearchTemplate 的使用

1.3.1、創建索引庫,設置映射

1.3.2、創建索引映射注意事項

1.3.3、簡單的 CRUD

1.3.4、三種構建搜索條件的方式

1.3.5、NativeQuery 搜索實戰

1.3.6、completionSuggestion 自動補全


一、SpringData ElasticSearch


1.1、環境配置

a)依賴如下:

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency><!--SpringBoot3 之后測試必須引入這個包--><dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>2.23.4</version><scope>test</scope></dependency>

b)配置文件如下:

spring:application:name: eselasticsearch:uris: env-base:9200

1.2、創建實體類

a)簡單結構如下(后續示例,圍繞此結構展開):

import org.springframework.data.annotation.Id
import org.springframework.data.elasticsearch.annotations.Document
import org.springframework.data.elasticsearch.annotations.Field
import org.springframework.data.elasticsearch.annotations.FieldType@Document(indexName = "album_info", )
data class AlbumInfoDo (/*** @Id: 表示文檔中的主鍵,并且會在保存在 ElasticSearch 數據結構中 {"id": "", "userId": "", "title": ""}*/@Id@Field(type = FieldType.Keyword)val id: Long? = null,/*** @Field: 描述 Java 類型中的屬性映射*      - name: 對應 ES 索引中的字段名. 默認和屬性同名*      - type: 對應字段類型,默認是 FieldType.Auto (會根據我們數據類型自動進行定義),但是建議主動定義,避免導致錯誤映射*      - index: 是否創建索引. text 類型創建倒排索引,其他類型創建正排索引.  默認是 true*      - analyzer: 分詞器名稱.  中文我們一般都使用 ik 分詞器(ik分詞器有 ik_smart 和 ik_max_word)*/@Field(name = "user_id", type = FieldType.Long)val userId: Long,@Field(type = FieldType.Text, analyzer = "ik_max_word")var title: String,@Field(type = FieldType.Text, analyzer = "ik_smart")var content: String,
)

b)復雜嵌套結構如下:

import org.springframework.data.annotation.Id
import org.springframework.data.elasticsearch.annotations.Document
import org.springframework.data.elasticsearch.annotations.Field
import org.springframework.data.elasticsearch.annotations.FieldType@Document(indexName = "album_list")
data class AlbumListDo(@Id@Field(type = FieldType.Keyword)var id: Long,@Field(type = FieldType.Nested) // 表示一個嵌套結構var userinfo: UserInfoSimp,@Field(type = FieldType.Text, analyzer = "ik_max_word")var title: String,@Field(type = FieldType.Text, analyzer = "ik_smart")var content: String,@Field(type = FieldType.Nested) // 表示一個嵌套結構var photos: List<AlbumPhotoSimp>,
)data class UserInfoSimp(@Field(type = FieldType.Long)val userId: Long,@Field(type = FieldType.Text, analyzer = "ik_max_word")val username: String,@Field(type = FieldType.Keyword, index = false)val avatar: String,
)data class AlbumPhotoSimp(@Field(type = FieldType.Integer, index = false)val sort: Int,@Field(type = FieldType.Keyword, index = false)val photo: String,
)

對于一個小型系統來說,一般也不會創建這種復雜程度的文檔,因為會涉及到很多一致性問題,?需要通過大量的 mq 進行同步,給系統帶來一定的開銷.?

因此,一般會將需要進行模糊查詢的字段存 Document 中(es 就擅長這個),而其他數據則可以在 Document 中以 id 的形式進行存儲. ? 這樣就既可以借助 es 高效的模糊查詢能力,也能減少為保證一致性而帶來的系統開銷. ?從 es 中查到數據后,再通過其他表的 id 從數據庫中拿數據即可(這點開銷,相對于從大量數據的數據庫中進行 like 查詢,幾乎可以忽略).

1.3、ElasticSearchTemplate 的使用

1.3.1、創建索引庫,設置映射

@SpringBootTest
class ElasticSearchIndexTests {@Resourceprivate lateinit var elasticsearchTemplate: ElasticsearchTemplate@Testfun test1() {//存在索引庫就刪除if (elasticsearchTemplate.indexOps(AlbumInfoDo::class.java).exists()) {elasticsearchTemplate.indexOps(AlbumInfoDo::class.java).delete()}//創建索引庫elasticsearchTemplate.indexOps(AlbumInfoDo::class.java).create()//設置映射elasticsearchTemplate.indexOps(AlbumInfoDo::class.java).putMapping(elasticsearchTemplate.indexOps(AlbumInfoDo::class.java).createMapping())}}

效果如下:?

1.3.2、創建索引映射注意事項

a)在沒有創建索引庫和映射的情況下,也可以直接向 es 庫中插入數據,如下代碼:

    @Testfun test2() {val obj = AlbumListDo(id = 1,userinfo = UserInfoSimp(userId = 1,username = "cyk",avatar = "env-base:9200"),title = "今天天氣真好",content = "早上起來,我要好好學習,然去公園散步~",photos = listOf(AlbumPhotoSimp(1, "www.photo.com/aaa"),AlbumPhotoSimp(2, "www.photo.com/bbb")))val result = elasticsearchTemplate.save(obj)println(result)}

即使上述代碼中 AlbumListDo 中有各種注解標記,但是不會生效!!! es 會根據插入的數據,自動轉化數據結構(無視你的注解).

因此,建議先創建索引庫和映射,再進行數據插入!

1.3.3、簡單的 CRUD

import jakarta.annotation.Resource
import org.cyk.es.model.AlbumInfoDo
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate
import org.springframework.data.elasticsearch.core.document.Document
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates
import org.springframework.data.elasticsearch.core.query.UpdateQuery@SpringBootTest
class ElasticSearchCRUDTests {@Resourceprivate lateinit var elasticsearchTemplate: ElasticsearchTemplate@Testfun testSave() {//保存單條數據val a1 = AlbumInfoDo(id = 1,userId = 10000,title = "今天天氣真好",content = "學習完之后,我要出去好好玩")val result = elasticsearchTemplate.save(a1)println(result)//保存多條數據val list = listOf(AlbumInfoDo(2, 10000, "西安六號線避雷", "前俯后仰。他就一直在那前后動。他背后是我朋友,我讓他不要擠了,他直接就急了,開始故意很大力的擠來擠去。"),AlbumInfoDo(3, 10000, "字節跳動快上車~", "#內推 #字節跳動內推 #互聯網"),AlbumInfoDo(4, 10000, "連王思聰也變得低調老實了", "如今的王思聰,不僅交女友的質量下降,在網上也不再像以前那樣隨意噴這噴那。顯然,資金的緊張讓他低調了許多"))val resultList = elasticsearchTemplate.save(list)resultList.forEach(::println)}@Testfun testDelete() {//根據主鍵刪除,例如刪除主鍵 id = 1 的文檔elasticsearchTemplate.delete("1", AlbumInfoDo::class.java)}@Testfun testGet() {//根據主鍵獲取文檔val result = elasticsearchTemplate.get("1", AlbumInfoDo::class.java)println(result)}@Testfun testUpdate() {//例如,修改 id = 1 的文檔val id = 1val title = "今天天氣不太好"val content = "天氣不好,只能在家里學習了。。。"val uq = UpdateQuery.builder(id.toString()).withDocument(Document.create().append("title", title).append("content", content)).build()val result = elasticsearchTemplate.update(uq, IndexCoordinates.of("album_info")).resultprintln(result.ordinal)println(result.name)}}

1.3.4、三種構建搜索條件的方式

關于搜索條件的構建,Spring 官網上給出了三種構建方式:Elasticsearch Operations :: Spring Data Elasticsearch

a)CriteriaQuery:允許創建查詢來搜索數據,而不需要了解 Elasticsearch 查詢的語法或基礎知識。它們允許用戶通過簡單地鏈接和組合 Criteria 對象來構建查詢,Criteria 對象指定被搜索文檔必須滿足的條件。

Criteria criteria = new Criteria("lastname").is("Miller") .and("firstname").is("James")                           
Query query = new CriteriaQuery(criteria);

b)StringQuery:這個類接受 Elasticsearch 查詢作為 JSON String。下面的代碼顯示了一個搜索名為“ Jack”的人的查詢:

Query query = new StringQuery("{ \"match\": { \"firstname\": { \"query\": \"Jack\" } } } ");
SearchHits<Person> searchHits = operations.search(query, Person.class);

c)NativeQuery:當您有一個復雜的查詢或者一個無法使用 Criteria API 表示的查詢時,例如在構建查詢和使用聚合時,可以使用 NativeQuery 類。

d)到底使用哪一種呢?在最新的這一版 SpringDataES 中,NativeQuery 中可以通過大量的 Lambda 來構建條件語句,并且外觀上也很符合 ElasticSearch DSL,那么對于比較熟悉原生的 DSL 語句的就建議使用 NativeQuery 啦.? 我本人也更傾向 NativeQuery,因此后續的案例都會使用它.

1.3.5、NativeQuery 搜索實戰

import co.elastic.clients.elasticsearch._types.SortOrder
import co.elastic.clients.json.JsonData
import jakarta.annotation.Resource
import org.cyk.es.model.AlbumInfoDo
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.data.domain.PageRequest
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate
import org.springframework.data.elasticsearch.client.elc.NativeQuery
import org.springframework.data.elasticsearch.core.query.HighlightQuery
import org.springframework.data.elasticsearch.core.query.highlight.Highlight
import org.springframework.data.elasticsearch.core.query.highlight.HighlightField
import org.springframework.data.elasticsearch.core.query.highlight.HighlightParameters@SpringBootTest
class SearchTests {@Resourceprivate lateinit var elasticsearchTemplate: ElasticsearchTemplate/*** 全文檢索查詢(match_all)*/@Testfun testMatchAllQuery() {val query = NativeQuery.builder().withQuery { q -> q.matchAll { it }}.build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)hits.forEach { println(it.content) }}/*** 精確查詢(match)*/@Testfun testMatchQuery() {val query = NativeQuery.builder().withQuery { q -> q.match {it.field("title").query("天氣")}}.build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)hits.forEach { println(it.content) }}/*** 精確查詢(term)*/@Testfun testTerm() {val query = NativeQuery.builder().withQuery { q -> q.term { t -> t.field("id").value("2")}}.build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)hits.forEach { println(it.content) }}/*** 范圍搜索*/@Testfun testRangeQuery() {val query = NativeQuery.builder().withQuery { q -> q.range { r -> r.field("id").gte(JsonData.of(1)).lt(JsonData.of(4)) // 大于等于 1,小于 4}}.build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)hits.forEach { println(it.content) }}/*** bool 復合搜索*/@Testfun testBoolQuery() {val query = NativeQuery.builder().withQuery { q -> q.bool { b -> b.must { m -> m.range { r -> r.field("id").gte(JsonData.of(1)).lt(JsonData.of(4)) // 大于等于 1,小于 4}}.mustNot { n -> n.match { mc -> mcmc.field("title").query("天氣")}}.should { s -> s.matchAll { it }}}}.build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)hits.forEach { println(it.content) }}/*** 排序 + 分頁*/@Testfun testSortAndPage() {//a) 方式一
//        val query = NativeQuery.builder()
//            .withQuery { q -> q
//                .matchAll { it }
//            }
//            .withPageable(
//                PageRequest.of(0, 3) //頁碼(從 0 開始),非偏移量
//                    .withSort(Sort.by(Sort.Order.desc("id")))
//            ).build()//b) 方式二val query = NativeQuery.builder().withQuery { q -> q.matchAll { it }}.withSort { s -> s.field { f->f.field("id").order(SortOrder.Desc) } }.withPageable(PageRequest.of(0, 3)) //頁碼(從 0 開始),非偏移量).build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)hits.forEach { println(it.content) }}@Testfun testHighLight() {//所有需要高亮的字段val highField = listOf(HighlightField("title"),HighlightField("content"))val query = NativeQuery.builder().withQuery { q ->q.multiMatch { ma -> ma.fields("title", "content").query("天氣")}}.withHighlightQuery(HighlightQuery(Highlight(HighlightParameters.builder().withPreTags("<span style='color:red'>") //前綴標簽.withPostTags("</span>") //后綴標簽.withFragmentSize(10) //高亮的片段長度(多少個幾個字需要高亮,一般會設置的大一些,讓匹配到的字段盡量都高亮).withNumberOfFragments(1) //高亮片段的數量.build(),highField),String::class.java)).build()val hits = elasticsearchTemplate.search(query, AlbumInfoDo::class.java)//hits.content 本身是沒有高亮數據的,因此這里需要手動處理hits.forEach {val result = it.content//根據高亮字段名稱,獲取高亮數據集合val titleList = it.getHighlightField("title")val contentList = it.getHighlightField("content")if (titleList.size > 0) result.title = titleList[0]if (contentList.size > 0) result.content = contentList[0]println(result)}}}

1.3.6、completionSuggestion 自動補全

a)自動補全的字段必須是 completion 類型.?
這里自動補全的字段為 title,通過 copyTo 將其拷貝到 suggestion 字段中,實現自動補全.
import org.springframework.data.annotation.Id
import org.springframework.data.elasticsearch.annotations.CompletionField
import org.springframework.data.elasticsearch.annotations.Document
import org.springframework.data.elasticsearch.annotations.Field
import org.springframework.data.elasticsearch.annotations.FieldType
import org.springframework.data.elasticsearch.core.suggest.Completion@Document(indexName = "album_doc")
data class AlbumSugDo (@Id@Field(type = FieldType.Keyword)val id: Long,@Field(name = "user_id", type = FieldType.Long)val userId: Long,@Field(type = FieldType.Text, analyzer = "ik_max_word", copyTo = ["suggestion"]) //注意,copyTo 的字段一定是 var 類型val title: String,@Field(type = FieldType.Text, analyzer = "ik_smart")val content: String,@CompletionField(maxInputLength = 100, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")var suggestion: Completion? = null, //注意,被 copyTo 的字段一定要是 var 類型
)

Ps:被 copyTo 的字段一定要是 var 類型

b)需求:在搜索框中輸入 “今天”,對其進行自動補全.

import co.elastic.clients.elasticsearch.core.search.FieldSuggester
import co.elastic.clients.elasticsearch.core.search.FieldSuggesterBuilders
import co.elastic.clients.elasticsearch.core.search.Suggester
import jakarta.annotation.Resource
import org.cyk.es.model.AlbumSugDo
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate
import org.springframework.data.elasticsearch.client.elc.NativeQuery
import org.springframework.data.elasticsearch.core.suggest.response.Suggest@SpringBootTest
class SuggestTests {@Resourceprivate lateinit var elasticsearchTemplate: ElasticsearchTemplate@Testfun init() {if(elasticsearchTemplate.indexOps(AlbumSugDo::class.java).exists()) {elasticsearchTemplate.indexOps(AlbumSugDo::class.java).delete()}elasticsearchTemplate.indexOps(AlbumSugDo::class.java).create()elasticsearchTemplate.indexOps(AlbumSugDo::class.java).putMapping(elasticsearchTemplate.indexOps(AlbumSugDo::class.java).createMapping())elasticsearchTemplate.save(listOf(AlbumSugDo(1, 10000, "今天發現西安真美", "西安真美麗啊,來到了鐘樓...."),AlbumSugDo(2, 10000, "今天六號線避雷", "前俯后仰。他就一直在那前后動。他背后是我朋友,我讓他不要擠了,他直接就急了,開始故意很大力的擠來擠去。"),AlbumSugDo(3, 10000, "字節跳動快上車~", "#內推 #字節跳動內推 #互聯網"),AlbumSugDo(4, 10000, "連王思聰也變得低調老實了", "如今的王思聰,不僅交女友的質量下降,在網上也不再像以前那樣隨意噴這噴那。顯然,資金的緊張讓他低調了許多")))}@Testfun suggestTest() {//模擬客戶端輸入的需要自動補全的字段val input = "今天"val limit = 10val fieldSuggester = FieldSuggester.Builder().text(input) //用戶輸入.completion(FieldSuggesterBuilders.completion().field("suggestion") //對哪個字段自動補全.skipDuplicates(true) //如果有重復的詞條,自動跳過.size(limit) //最多顯示 limit 條數據.build()).build()val query = NativeQuery.builder().withSuggester(Suggester.of { s -> s.suggesters("sug1", fieldSuggester) }) //參數一: 自定義自動補全名.build()val hits = elasticsearchTemplate.search(query, AlbumSugDo::class.java)val suggestList = hits.suggest?.getSuggestion("sug1")?.entries?.get(0)?.options?.map(::map) ?: emptyList()println(suggestList)}private fun map(hit: Suggest.Suggestion.Entry.Option): String {return hit.text}}

上述代碼中的 hits 結構如下:

運行結果:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/12696.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/12696.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/12696.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

深度學習面試問題 | 降維

本文給大家帶來的百面算法工程師是深度學習降維面試總結&#xff0c;文章內總結了常見的提問問題&#xff0c;旨在為廣大學子模擬出更貼合實際的面試問答場景。在這篇文章中&#xff0c;我們還將介紹一些常見的深度學習面試問題&#xff0c;并提供參考的回答及其理論基礎&#…

【面試必看】MySQL部分

MySQL 1. 基礎 1. 什么是關系型數據庫&#xff1f; 一種建立在關系模型的基礎上的數據庫。關系模型表明了數據庫中所存儲的數據之間的聯系&#xff08;一對一、一對多、多對多&#xff09;。各種表中&#xff08;比如用戶表&#xff09;&#xff0c;表中的每一行就存放著一條…

【leetcode面試經典150題】-26. 刪除有序數組中的重復項

26. 刪除有序數組中的重復項 1 題目介紹1 個人解題思路1.1 解題代碼1.2 思路解析 2、分析官方題解2.1 快慢雙指針 1 題目介紹 給你一個 非嚴格遞增排列 的數組 nums &#xff0c;請你 原地 刪除重復出現的元素&#xff0c;使每個元素 只出現一次 &#xff0c;返回刪除后數組的新…

新手小白如何使用云平臺復現論文代碼——體驗yolov8監控交通流

介紹&#xff1a;YOLOv8 是一種開源目標檢測算法&#xff08;模型&#xff09;&#xff0c;是 YOLO(You Only Look Once) 系列算法的最新版本。它使用單次預測框架對圖像中的對象進行定位和分類。這種方法可以檢測多個對象&#xff0c;并且速度更快&#xff0c;準確率更高。 參…

framework ‘CoreAudioTypes‘ not found

幾天前我升級Xcode15之后遇到了這個問題。關于“CoreAudioTypes”的信息完全是誤導。在我的例子中&#xff0c;原因是在刪除一些舊代碼時&#xff0c;我不小心刪除了仍然需要的類。然而&#xff0c;在構建時彈出的唯一消息是關于“CoreAudioTypes”——當我恢復丟失的類時&…

一例Phorpiex僵尸網絡變種的分析

概述 這是一例Phorpiex僵尸網絡變種&#xff0c;通過NSIS打包&#xff0c;加載惡意dll(Flaminius.dll)&#xff0c;讀取dat文件&#xff08;Preoral.dat&#xff09;&#xff0c;在內存解密并解壓縮出一個Pe&#xff0c;創建同名傀儡進程并注入。通過可移動存儲介質傳播&#…

告別信用卡綁定煩惱:探索這個全功能的Azure語音替代品,包含AI視頻制作!(微軟Azure語音替代方案)

文章目錄 ?? 介紹 ???? 演示環境 ???? 文章內容 ???? 語音合成的替代方案?? 功能特色?? 使用步驟示例?? 相關鏈接 ???? 介紹 ?? 雖然微軟Azure語音服務為個人用戶提供了充足的免費語音合成額度,但其注冊過程中的信用卡綁定要求、繁瑣的API配置步驟卻…

【BOSS直聘爬取系統功能介紹】

完整代碼關注公眾號 &#xff1a; 爬取網站&#xff1a;BOSS直聘&#xff1a;https://www.zhipin.com/ 難點 1. boss直聘不論什么崗位都只會展示10頁數據&#xff0c;就算在網頁里加到了11&#xff0c;內容也會和10一樣。 2.多次訪問會有驗證碼需要登錄&#xff0c;這部分需…

短視頻世上無人再似她:成都鼎茂宏升文化傳媒公司

短視頻世上無人再似她 —— 記憶中的光影傳奇 在短視頻盛行的今天&#xff0c;每一位創作者都在用鏡頭捕捉生活&#xff0c;記錄世界&#xff0c;但有那么一位藝術家&#xff0c;她的作品如同夜空中最亮的星&#xff0c;即便是在信息洪流中&#xff0c;也依然閃耀著獨一無二的…

jupyter_lab修改默認目錄

1、配置jupyterlab和jupyternotebook的默認工作路徑。 2、不廢話&#xff0c;直接上步驟 在Jupyter Notebook或者cmd命令行中輸入&#xff1a; jupyter notebook --generate-config jupyter-lab --generate-config生成配置文件“jupyter_notebook_config.py"和jupyter_la…

高通Android 11/12/13 通過包名設置默認launcher

背景&#xff1a;最近在封裝供第三應用系統SDK 接口&#xff0c;遇到一個無法通過包名設置主launcher代碼坑所以記錄下。 涉及類roles.xml # <!---~ see com.android.settings.applications.defaultapps.DefaultHomePreferenceController~ see com.android.settings.appl…

重啟服務器后node節點顯示NotReady

場景&#xff1a;夜間進行了斷電維護&#xff0c;重啟后發現業務無法使用&#xff0c;檢查發現一個node節點顯示NotReady. 去到目標服務器查看kubelet服務未成功啟動 journalctl -u kubelet 執行journalctl -u kubelet 查看日志發現提示&#xff1a; ailed to run Kubelet: run…

BFS和DFS優先搜索算法

1. BFS與DFS 1.1 BFS DFS即Depth First Search&#xff0c;深度優先搜索。它是一種圖遍歷算法&#xff0c;它從一個起始點開始&#xff0c;逐層擴展搜索范圍&#xff0c;直到找到目標節點為止。 這種算法通常用于解決“最短路徑”問題&#xff0c;比如在迷宮中找到從起點到終…

鐵路機輛作業移動智能終端的特點是什么?

在鐵路機輛作業的現代化進程中&#xff0c;移動智能終端以其獨特的優勢成為了不可或缺的裝備。這些終端以其高度的便攜性&#xff0c;使得工作人員能夠隨時隨地處理各種作業任務&#xff0c;極大地提升了工作效率。它們具備出色的抗干擾性和高防護性&#xff0c;能夠在復雜多變…

算法學習系列(六十一):樹形DP

目錄 引言一、沒有上司的舞會二、樹的重心三、樹的最長路徑四、樹的中心 引言 關于這個樹形 D P DP DP 代碼其實都是那一套&#xff0c;核心還是在于思維上的難度&#xff0c;關鍵是這個思路你能不能想明白&#xff0c;想明白了就非常的簡單&#xff0c;因為代碼幾乎長得都差…

LLM應用-prompt提示:讓大模型總結生成思維導圖

第一步&#xff1a;大模型生成markdown思維導圖格式 例如&#xff1a;kimi 總結pdf文檔案例&#xff1a; 生成的markdown格式&#xff1a; # 知識圖譜的構建及應用 ## 一、知識圖譜的構建 ### 1. 數據采集 - 來源&#xff1a;結構化數據庫、半結構化網頁、非結構化文本 - 預處…

React useState 的調用規則與最佳實踐:為何不在條件語句內使用 useState

在React中&#xff0c;useState 的調用確實有一些特定的規則和最佳實踐 以下是為什么通常不推薦在 if 語句內調用 useState 的原因&#xff1a; 1、Hooks 規則&#xff1a; React Hooks 的規則之一是&#xff0c;你應該在函數組件的頂層調用它們&#xff0c;而不是在循環、條…

技術管理者如何建立權威?

很多技術管理者經常抱怨管理不好做&#xff0c;還是做技術容易&#xff0c;完全受自己控制。員工一點都不聽自己的&#xff0c;安排的工作拖拖拉拉&#xff0c;一點執行力都沒有。 不是管理難做&#xff0c;而是管理者沒有建立權威。如何建立權威&#xff0c;參考以下四點。 …

PCIE V3.0物理層協議學習筆記

一、說明 PCI-Express(peripheral component interconnect express)是一種高速串行計算機擴展總線標準&#xff0c;它原來的名稱為“3GIO”&#xff0c;是由英特爾在2001年提出的&#xff0c;旨在替代舊的PCI&#xff0c;PCI-X和AGP總線標準。 PCIe屬于高速串行點對點雙通道高…