Lucene.Net學習心得(轉載)
http://kb.cnblogs.com/page/52642/
一、Lucene點滴
(發音為['lusen]),我經常就讀鹿神,是頭活蹦亂跳的好鹿,研究它吧,保證感覺它很神!Lucene是一個非常優秀的開源的全文搜尋引擎,我們可以在它的上面開發出各種全文搜尋的應用來。Lucene在國外有很高的知名度,現在已經是Apache的頂級專案。
二、倒排索引原理簡述
Lucene是一個高效能的java全文檢索工具包,它使用的是倒排檔案索引結構。具體解釋演算法理論就不講了,直接用例子來說明吧,如果你認真仔細的讀懂例子,真正領會了其中的思想,你肯定就明白了Lucene索引的基本原理!記住:理解!把例子用你自己的語言表述出來,就是翻譯成你自己的東西,以後你想自己寫,也就是換成計算機語言再翻譯一次!!
Lucene結構及相應的生成演算法如下:
我們設有兩篇文章1和2
文章1的內容為:Tom lives in Guangzhou,I live in Guangzhou too.
文章2的內容為:He once lived in Shanghai.
1)全文分析:
由於Lucene是基於關鍵詞索引和查詢的,首先我們要取得這兩篇文章的關鍵詞,通常我們需要如下處理措施
a. 我們現在有的是文章內容,即一大串字串,我們先要找出全文字串中的所有單詞,即分詞。英文單詞由於用空格分隔,比較好處理。中文單詞間是連在一起的需要特殊的分詞處理。(中文通常用詞典的方式比較準確)
b. 文章中的”in”, “once” “too”等詞沒有什麼實際意義,中文中的“的”“是”等字通常也無具體含義,這些不代表概念的詞可以過濾掉,即分詞解析中的過濾
c. 使用者通常希望查“He”時能把含“he”,“HE”的文章也找出來,所以所有單詞需要統一大小寫。即解析過程中的額外處理(使用者可以根據自己需要增加多重處理)。
d. 使用者通常希望查“live”時能把含“lives”,“lived”的文章也找出來,所以需要把“lives”,“lived”還原成“live”即進一步優化處理(可以更人性更友好)
e. 文章中的標點符號通常不表示某種概念,也可以過濾掉
所有上面描述的步驟在lucene中都由Analyzer類完成!你瞭解了過程,你就可以根據自己的興趣或者需要去關心特點的步驟相關程式碼,或者自己進一步添磚加瓦擴充套件功能。
經過上面處理後
文章1的所有關鍵詞為:[tom] [live] [guangzhou] [live] [guangzhou]
文章2的所有關鍵詞為:[he] [live] [shanghai]
2) 倒排索引:
有了關鍵詞後,我們就可以建立倒排索引了。
上面經過解析後的對應關係是:“文章號”對“文章中所有關鍵詞”。
這種對應比較符合我們正常的思維習慣,反過來對應的話,就要顛倒思維,所以這種演算法叫做倒排! 倒排索引把這個關係倒過來,變成:“關鍵詞”對“擁有該關鍵詞的所有文章號”。文章1,2經過倒排後變成
關鍵詞 文章號
guangzhou 1
he 2
i 1
live 1,2
shanghai 2
tom 1
進一步擴充套件上述基本倒排索引,通常我們僅知道關鍵詞在哪些文章中出現還不夠,我們還需要知道關鍵詞在文章中出現次數和出現的位置,通常有兩種位置:a)字元位置,即記錄該詞是文章中第幾個字元(優點是關鍵詞亮顯時定位快);b)關鍵詞位置,即記錄該詞是文章中第幾個關鍵詞(優點是節約索引空間、片語(phase)查詢快),lucene 中記錄的就是這種位置。
加上“出現頻率”和“出現位置”資訊後,我們的索引結構充實後變為:
關鍵詞 | 文章號 | [出現頻率] | 出現位置 |
guangzhou | 1 | [2] | 3,6 |
he | 2 | [1] | 1 |
i | 1 | [1] | 4 |
live | 1 | [2] | 2,5 |
2 | [1] | 2 | |
shanghai | 2 | [1] | 3 |
tom | 1 | [1] | 1 |
以第4行的 live 詞語索引記錄作例項我們說明一下該結構:
live在文章1中出現了2次,文章2中出現了一次,它的出現位置為“2,5,2”這表示什麼呢?我們需要結合文章號和出現頻率來分析,文章1中出現了2次,那麼“2,5”就表示live在文章1中出現的兩個位置,文章2中出現了一次,剩下的“2”就表示live是文章2中第 2個關鍵字。
以上就是lucene索引結構中最核心的部分。是不是描述起來很簡單,沒錯,其實也就是這麼簡單!演算法都是人想出來的,毛主席說過辦法總比困難多,計算機演算法也不例外,你何必恐懼它呢,本來就是很容易的事情!!!
【進一步深入探索,如果你不想深入,完全可以略過不看】
如果你對計算機演算法和資料結構稍有研究,你就很容易發現,我們上面生成的倒排索引關鍵字是按字母字元順序排列的(Lucene沒有使用B樹結構),因此Lucene可以用二元搜尋演算法快速定位關鍵詞。
具體實現時Lucene將上面三列分別作為詞典檔案(Term Dictionary)、頻率檔案(frequencies)、位置檔案(positions)儲存。其中詞典檔案不僅儲存有每個關鍵詞,還保留了指向頻率檔案和位置檔案的指標,通過指標可以找到該關鍵字的頻率資訊和位置資訊。
Lucene中使用了field的概念,用於表達資訊所在位置(如標題中,文章中,url中),在建索引中,該field資訊也記錄在詞典檔案中,每個關鍵詞都有一個field資訊(因為每個關鍵字一定屬於一個或多個field)。
為了減小索引檔案的大小,Lucene對索引還使用了壓縮技術。首先,對詞典檔案中的關鍵詞進行了壓縮,關鍵詞壓縮為<字首長度,字尾>,例如:當前詞為“阿拉伯語”,上一個詞為“阿拉伯”,那麼“阿拉伯語”壓縮為<3,語>。其次大量用到的是對數字的壓縮,數字只儲存與上一個值的差值(這樣可以減小數字的長度,進而減少儲存該數字需要的位元組數)。例如當前文章號是16389(不壓縮要用3個位元組儲存),上一文章號是16382,壓縮後儲存7(只用一個位元組)。注意是“上一個詞”。由於詞典是按順序排列的,這種壓縮方法的效果會非常顯著。
三、全文檢索框架的實現機制:
Lucene的API介面設計的比較通用,輸入輸出結構都很像資料庫的表==>記錄==>欄位,所以很多傳統的應用的檔案、資料庫等都可以比較方便的對映到Lucene的儲存結構/介面中。總體上看:可以先把Lucene當成一個支援全文索引的資料庫系統。
比較一下Lucene資料儲存和傳統的關係資料庫之間的區別:
Lucene | 資料庫 |
索引資料來源:doc(field1,field2...) doc(field1,field2...) \ indexer / _____________ | Lucene Index | -------------- / searcher \ 結果輸出:Hits(doc(field1,field2) doc(field1...)) |
索引資料來源:record(field1,field2...) record(field1..) \ SQL: insert/ _____________ | DB Index | ------------- / SQL: select \ 結果輸出:results(record(field1,field2..) record(field1...)) |
Document:一個需要進行索引的“單元,一個Document由多個欄位組成 | Record:記錄,包含多個欄位 |
Field:欄位 | Field:欄位 |
Hits:查詢結果集,由匹配的Document組成 | RecordSet:查詢結果集,由多個Record組成 |
請一定記住:全文檢索 ≠ 資料庫SQL語句中的 like "%keyword%"
由於資料庫索引不是為全文索引設計的,因此,使用like"%keyword%"時,資料庫索引是不起作用的,在使用like查詢時,搜尋過程又變成類似於一頁頁翻書的遍歷過程了,所以對於含有模糊查詢的資料庫服務來說,LIKE對效能的危害是極大的。如果是需要對多個關鍵詞進行模糊匹配:like"%keyword1%" and like"%keyword2%" ...其效率也就可想而知了。
通常比較厚的書籍後面常常附關鍵詞索引表(比如:北京:12,34頁,上海:3,77頁……),它能夠幫助讀者比較快地找到相關內容的頁碼。而資料庫索引能夠大大提高查詢的速度原理也是一樣,想像一下通過書後面的索引查詢的速度要比一頁一頁地翻內容高多少倍……而索引之所以效率高,另外一個原因是它是排好序的。對於檢索系統來說核心是一個排序問題。
所以建立一個高效檢索系統的關鍵是建立一個類似於科技索引一樣的反向索引機制,將資料來源(比如多篇文章)排序順序儲存的同時,有另外一個排好序的關鍵詞列表,用於儲存關鍵詞==>文章對映關係,利用這樣的對映關係索引:[關鍵詞==>出現關鍵詞的文章編號,出現次數(甚至包括位置:起始偏移量,結束偏移量),出現頻率],檢索過程就是把模糊查詢變成多個可以利用索引的精確查詢的邏輯組合的過程。從而大大提高了多關鍵詞查詢的效率,所以,全文檢索問題歸結到最後是一個排序問題。
由此可以看出模糊查詢相對資料庫的精確查詢是一個非常不確定的問題,這也是大部分資料庫對全文檢索支援有限的原因。
Lucene最核心的特徵是通過特殊的索引結構實現了傳統資料庫不擅長的全文索引機制,並提供了擴充套件介面,以方便針對不同應用的定製。
我們對比一下Lucene全文索引和關係資料庫模糊查詢 演算法區別:
Lucene全文索引引擎 | 資料庫 | |
索引 | 將資料來源中的資料都通過全文索引一一建立倒排索引 | 對於LIKE查詢來說,資料傳統的索引是根本用不上的。資料需要逐個便利記錄進行GREP式的模糊匹配,比有索引的搜尋速度要有多個數量級的下降。 |
匹配效果 | 通過詞元(term)進行匹配,通過語言分析介面的實現,可以實現對中文等非英語的支援。 | 使用:like "%net%" 會把netherlands也匹配出來, 多個關鍵詞的模糊匹配:使用like "%com%net%":就不能匹配詞序顛倒的xxx.net..xxx.com |
匹配度 | 有匹配度演算法,將匹配程度(相似度)比較高的結果排在前面。 | 沒有匹配程度的控制:比如有記錄中net出現5詞和出現1次的,結果是一樣的 |
結果輸出 | 通過特別的演算法,將最匹配度最高的頭100條結果輸出,結果集是緩衝式的小批量讀取的。 | 返回所有的結果集,在匹配條目非常多的時候(比如上萬條)需要大量的記憶體存放這些臨時結果集。 |
可定製性 | 通過不同的語言分析介面實現,可以方便的定製出符合應用需要的索引規則(包括對中文的支援) | 沒有介面或介面複雜,無法定製 |
結論 | 高負載的模糊查詢應用,需要負責的模糊查詢的規則,索引的資料量比較大 | 使用率低,模糊匹配規則簡單或者需要模糊查詢的資料量少 |
全文檢索和資料庫應用最大的不同在於:讓最相關的頭100條結果滿足98%以上使用者的需求。
Lucene的創新之處:
大部分的搜尋(資料庫)引擎都是用B樹結構來維護索引,索引的更新會導致大量的IO操作,Lucene在實現中,對此稍微有所改進:不是維護一個索引檔案,而是在擴充套件索引的時候不斷建立新的索引檔案,然後定期的把這些新的小索引檔案合併到原先的大索引中(針對不同的更新策略,批次的大小可以調整),這樣在不影響檢索的效率的前提下,提高了索引的效率。
Lucene和其他一些全文檢索系統/應用的比較:
Lucene | 其他開源全文檢索系統 | |
增量索引和批量索引 | 可以進行增量的索引(Append),可以對於大量資料進行批量索引,並且介面設計用於優化批量索引和小批量的增量索引。 | 很多系統只支援批量的索引,有時資料來源有一點增加也需要重建索引。 |
資料來源 | Lucene沒有定義具體的資料來源,而是一個文件的結構,因此可以非常靈活的適應各種應用(只要前端有合適的轉換器把資料來源轉換成相應結構)。 | 很多系統只針對網頁,缺乏其他格式文件的靈活性。 |
索引內容抓取 | Lucene的文件是由多個欄位組成的,甚至可以控制那些欄位需要進行索引,那些欄位不需要索引,近一步索引的欄位也分為需要分詞和不需要分詞的型別: 需要進行分詞的索引,比如:標題,文章內容欄位 不需要進行分詞的索引,比如:作者/日期欄位 |
缺乏通用性,往往將文件整個索引了 |
語言分析 | 通過語言分析器的不同擴充套件實現: 可以過濾掉不需要的詞:an the of 等, 西文語法分析:將jumps jumped jumper都歸結成jump進行索引/檢索 非英文支援:對亞洲語言,阿拉伯語言的索引支援 |
缺乏通用介面實現 |
查詢分析 | 通過查詢分析介面的實現,可以定製自己的查詢語法規則: 比如: 多個關鍵詞之間的 + - and or關係等 |
功能較強大 |
併發訪問 | 能夠支援多使用者的使用 | 功能較強大 |
四、關於亞洲語言的的切分詞問題(Word Segment)
對於中文來說,全文索引首先還要解決一個語言分析的問題,對於英文來說,語句中單詞之間是天然通過空格分開的,但亞洲語言的中日韓文語句中的字是一個字挨一個,所有,首先要把語句中按“詞”進行索引的話,這個詞如何切分出來就是一個很大的問題。
首先,肯定不能用單個字元作(si-gram)為索引單元,否則查“上海”時,不能讓含有“海上”也匹配。但一句話:“北京天安門”,計算機如何按照中文的語言習慣進行切分呢?“北京 天安門” 還是“北 京 天安門”?讓計算機能夠按照語言習慣進行切分,往往需要機器有一個比較豐富的詞庫才能夠比較準確的識別出語句中的單詞。
另外一個解決的辦法是採用自動切分演算法:將單詞按照2元語法(bigram)方式切分出來,比如:
"北京天安門" ==> "北京 京天 天安 安門"。
這樣,在查詢的時候,無論是查詢"北京" 還是查詢"天安門",將查詢片語按同樣的規則進行切分:"北京","天安安門",多個關鍵詞之間按與"and"的關係組合,同樣能夠正確地對映到相應的索引中。這種方式對於其他亞洲語言:韓文,日文都是通用的。
基於自動切分的最大優點是沒有詞表維護成本,實現簡單,缺點是索引效率低,但對於中小型應用來說,基於2元語法的切分還是夠用的。基於2元切分後的索引一般大小和原始檔差不多,而對於英文,索引檔案一般只有原檔案的30%-40%不同。
自動切分 | 詞表切分 | |
實現 | 實現非常簡單 | 實現複雜 |
查詢 | 增加了查詢分析的複雜程度 | 適於實現比較複雜的查詢語法規則 |
儲存效率 | 索引冗餘大,索引幾乎和原文一樣大 | 索引效率高,為原文大小的30%左右 |
維護成本 | 無詞表維護成本 | 詞表維護成本非常高:中日韓等語言需要分別維護。 還需要包括詞頻統計等內容 |
適用領域 | 嵌入式系統:執行環境資源有限 分散式系統:無詞表同步問題 多語言環境:無詞表維護成本 |
對查詢和儲存效率要求高的專業搜尋引擎 |
目前比較大的搜尋引擎的語言分析演算法一般是基於以上2個機制的結合。
五、Lucene的結構框架:
注意:Lucene中的一些比較複雜的詞法分析是用JavaCC生成的(JavaCC:JavaCompilerCompiler,純Java的詞法分析生成器),所以如果從原始碼編譯或需要修改其中的QueryParser、定製自己的詞法分析器,還需要從https://javacc.dev.java.net/下載javacc。
Lucene的組成結構:對於外部應用來說索引模組(index)和檢索模組(search)是主要的外部應用入口。
org.apache.Lucene.search/ | 搜尋入口 |
org.apache.Lucene.index/ | 索引入口 |
org.apache.Lucene.analysis/ | 語言分析器 |
org.apache.Lucene.queryParser/ | 查詢分析器 |
org.apache.Lucene.document/ | 儲存結構 |
org.apache.Lucene.store/ | 底層IO/儲存結構 |
org.apache.Lucene.util/ | 一些公用的資料結構 |
六、從Lucene學到更多:
Luene的確是一個面對物件設計的典範。如果你要學習面向物件程式設計,你要學習java,建議你學習Lucene吧,玩一個實實在在的專案,而且是有名的基礎專案,在無形之中你既可以學習這個專案的使用,又可以學習java語法,又可以學習大師們的程式碼技巧,還可以以後為Lucene做點什麼,真的你可以一舉多得!!!何樂不為呢?!
- 所有的問題都通過一個額外抽象層來方便以後的擴充套件和重用:你可以通過重新實現來達到自己的目的,而對其他模組而不需要;
- 簡單的應用入口Searcher, Indexer,並呼叫底層一系列元件協同的完成搜尋任務;
- 所有的物件的任務都非常專一:比如搜尋過程:QueryParser分析將查詢語句轉換成一系列的精確查詢的組合(Query),通過底層的索引讀取結構IndexReader進行索引的讀取,並用相應的打分器給搜尋結果進行打分/排序等。所有的功能模組原子化程度非常高,因此可以通過重新實現而不需要修改其他模組。
- 除了靈活的應用介面設計,Lucene還提供了一些適合大多數應用的語言分析器實現(SimpleAnalyser,StandardAnalyser),這也是新使用者能夠很快上手的重要原因之一。
----------------------------------------------------
示例:
日常開發中,相信大家經常會用like去匹配一些資料,同時我們也知道,like往往會導致全表掃描,當資料量越來越大的時候,我們會糾結於
資料庫的龜速查詢,此時我們必須另尋蹊蹺,這時lucene就可以大顯身手了。
首先我們做一個demo,向資料庫中插入10w條資料,總共778M。
接下來,我們搜尋下新聞內容中包含“流行”的記錄。
mmd,檢索一下要78s,是誰都要砸了面前的破機子。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using Lucene.Net.Index; 6 using Lucene.Net.Store; 7 using Lucene.Net.Analysis.Standard; 8 using Lucene.Net.Documents; 9 using System.Data; 10 using System.Diagnostics; 11 using Lucene.Net.Search; 12 13 using Lucene.Net.QueryParsers; 14 15 namespace First 16 { 17 class Program 18 { 19 static string path = @"D:\Sample"; 20 21 static void Main(string[] args) 22 { 23 //建立索引 24 CreateIndex(); 25 26 var watch = Stopwatch.StartNew(); 27 28 //搜尋 29 IndexSearcher search = new IndexSearcher(path); 30 31 //查詢表示式 32 QueryParser query = new QueryParser(string.Empty, new StandardAnalyzer()); 33 34 //query.parse:注入查詢條件 35 var hits = search.Search(query.Parse("Content:流行")); 36 37 for (int i = 0; i < hits.Length(); i++) 38 { 39 Console.WriteLine("當前內容:{0}", hits.Doc(i).Get("Content").Substring(0, 20) + "..."); 40 } 41 42 watch.Stop(); 43 44 Console.WriteLine("搜尋耗費時間:{0}", watch.ElapsedMilliseconds); 45 } 46 47 static void CreateIndex() 48 { 49 //建立索引庫目錄 50 var directory = FSDirectory.GetDirectory(path, true); 51 52 //建立一個索引,採用StandardAnalyzer對句子進行分詞 53 IndexWriter indexWriter = new IndexWriter(directory, new StandardAnalyzer()); 54 55 var reader = DbHelperSQL.ExecuteReader("select * from News"); 56 57 while (reader.Read()) 58 { 59 //域的集合:文件,類似於表的行 60 Document doc = new Document(); 61 62 //要索引的欄位 63 doc.Add(new Field("ID", reader["ID"].ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED)); 64 doc.Add(new Field("Title", reader["Title"].ToString(), Field.Store.NO, Field.Index.ANALYZED)); 65 doc.Add(new Field("Content", reader["Content"].ToString(), Field.Store.YES, Field.Index.ANALYZED)); 66 67 indexWriter.AddDocument(doc); 68 } 69 70 reader.Close(); 71 72 //對索引檔案進行優化 73 indexWriter.Optimize(); 74 75 indexWriter.Close(); 76 } 77 } 78 }
我靠,448ms,頓時78s黯然失色,當然這個時間是不包含"建立索引“的時間,從時間複雜度上來說,這種預載入索引算是常量。
作為入門,簡單的介紹下lucene的實現過程,首先lucene主要分成兩步:"索引"和"搜尋"。
一:索引:
相信大家對索引還是比較熟悉的,lucene能夠將我們內容切分成很多詞,然後將詞作為key,建立“倒排索引”,然後放到索引庫中,在上面
的例子中,我們看到了索引過程中使用到了IndexWriter,FSDirectory,StandardAnalyzer,Document和Field這些類,下面簡要分析下。
1:IndexWriter
我們看到該類有一個AddDocument方法,所以我們認為該類實現了索引的寫入操作。
2:FSDirectory
這個就更簡單了,提供了索引庫的存放位置,比如我們這裡的D:\Sample,或許有人問,能不能存放在記憶體中,在強大的lucene面前當然
可以做到,lucene中的RAMDirectory就可以實現,當然我們的記憶體足夠大的話,還是可以用記憶體承載索引庫,進而提高搜尋的效率。
3:StandardAnalyzer
這個算是索引過程中最最關鍵的一步,也是我們使用lucene非常慎重考慮的東西,之所以我們能搜尋秒殺,關鍵在於我們如何將輸入的內容
進行何種形式的切分,當然不同的切分形式誕生了不同的分析器,StandardAnalyzer就是一個按照單字分詞的一種分析器,詳細的介紹後續文
章分享。
4:Document
在上面的例子可以看到,他是承載field的集合,然後新增到IndexWriter中,有點類似表中的行的概念。
5: Field
提供了對要分析的欄位進行何種處理,以KV形式呈現。
①:Field.Store.YES, Field.Index.NOT_ANALYZED 表示對索引欄位採取:原樣儲存並且不被StandardAnalyzer進行切分。
②: Field.Store.NO, Field.Index.ANALYZED 不儲存但是要被StandardAnalyzer切分。
二:搜尋
這個比較容易,根據我們輸入的詞lucene能夠在索引庫中快速定位到我們要找的詞,同樣我們可以看到IndexSearcher,QueryParser,Hits。
1:IndexSearcher
這個我們可以理解成以只讀的形式開啟由IndexWriter建立的索引庫,search給QueryParser提供了查詢的橋樑。
2:QueryParser
這玩意提供了一個parse方法能夠將我們要查詢的詞轉化為lucene能夠理解了查詢表示式。
3:Hits
這個就是獲取匹配結果的一個指標,優點類似C#中的延遲載入,目的都是一樣,提高效能。
相關推薦
Lucene.Net學習心得(轉載)
http://kb.cnblogs.com/page/52642/ 一、Lucene點滴 (發音為['lusen]),我經常就讀鹿神,是頭活蹦亂跳的好鹿,研究它吧,保證感覺它很神!Lucene是一個非常優秀的開源的全文搜尋引擎,我們可以在它的上面開發出各種全文搜尋的應用來。Lucene在國外有很
verilog語法學習心得(轉載)
verilog語法學習心得 1.數位電路基礎知識: 布林代數、門級電路的內部電晶體結構、組合邏輯電路分析與設計、觸發器、時序邏輯電路分析與設計 2.數字系統的構成: 感測器 AD 數字處理器 DA 執行部件 3.程式通在硬體上的執行過程: C語言(經過編譯)
.net學習路線(轉載)
入門篇 1.學習面向物件(OOP)的程式設計思想 許多高階語言都是面向物件的程式設計,.NET也不例外。如果您第一次接觸面向物件的程式設計,就必須理解類、物件、欄位、屬性、方法和事件、封裝、繼承和多型性、過載、重寫等概念。需要說明的是,微軟的產品幫助文件做得非常完
Android學習心得(13) --- Android代碼混淆(1)
簽名 ref nes 三分 pen key this tool prop 我在博客上發表一些我的Android學習心得,希望對大家能有幫助。 這一篇我們講述一下最新的ADT環境下怎樣進行Android混淆 在新版本號的ADT創建項目時。混碼的文
機器學習算法基礎概念學習總結(轉載)
原則 不清楚 tof 條件 cnblogs 偽代碼 相關關系 什麽 最近鄰 來源:lantian0802的專欄 blog.csdn.net/lantian0802/article/details/38333479 一、基礎概念
ASP.NET學習筆記(4)——上傳圖片
bmi guid ted 介紹 dir filename content put ima 說明(2017-10-8 23:03:43): 1. 後面的內容都是一些雜七雜八的,零零碎碎的,之前都直接略過了,不過其實還是挺重要的,這次重新學習要認認真真敲一遍。 2. 明天中午9
ASP.NET學習筆記(6)——jQuery的Ajax基本操作
stat password ash page serve () c# content scrip 說明(2017-11-5 15:49:29): 1. jQuery裏封裝了三個方法,$.get,$.post和$.ajax,其中$.ajax是返回原生的XMLHttpReque
Java學習計劃(轉載)
建立 轉載 java編程思想 背景 自己 告訴 清晰 入行 距離 第一部分 在搭建SSM的過程中,可能會經常接觸到一個叫maven的工具。這個工具也是你以後工作當中幾乎是必須要使用的工具,所以你在搭建SSM的過程中,也可以順便了解一下maven的知識。在你目前這個階段,你只
C++學習心得(一)
eof gpo pre typeid 學習 div ctrl+z c++ str 2018-01-20 while (cin >> n)//終止可以使用輸入eof或Ctrl+Z for (auto &c : str) cout <
《安全運維工程師成長手冊》學習筆記(轉載)
tps 成長 要掌握 黑客 行業 安全行業 工作 屬於 接口 前言 (0)“識人面相” 明確自身位置、技術能力、以及希望達到的高度。物以類聚,人以群分;選對團隊,跟準人,才能在這”惡劣”的環境中生存下去。 這一部分的內容是從黃登老師的自身經歷出發,先介紹了他的職業生涯,
Android學習心得(一):
1、活動類處理啟動與關閉活動的相關方法及說明 方法 說明 StartActivity(intent) 使用引數意圖啟動新活動,此方法是重寫Context類實現的原始版本 startA
vuex 2.0學習心得(下)--- getter
vuex2.0基本使用(3) --- getter 1. Getter 就是把元件中共有的對state的操作進行了提取,它就相當於對state的computed.所以它會獲得state作為第一個引數。 2. 有的元件中獲取到 store中的state,&nb
vuex 2.0學習心得(中) mutation&action
Vuex (vue2.0) 基礎mutation&action(理解) Vuex採用和Redux類似的單向資料流的方式來管理資料。使用者介面負責觸發動作(Action)進而改變對應狀態(State),從而反映到檢視(View)上。如下圖所示: 完整的Vuex用
vuex 2.0學習心得(上)
Vuex (vue2.0) 基礎(理解) 相關詞彙認識 1. devtools 工具 2. backbend API後臺資料介面文件 3.&nb
大資料學習路線(轉載)
學習路線文章 哎,都是淚!!! 一、大資料技術基礎 1、linux操作基礎 linux系統簡介與安裝 linux常用命令–檔案操作 linux常用命令–使用者管理與許可權 linux常用命令–系統管理 linux常用命令–免密登陸配置與網路管理 linux上常用軟體安裝 linux本地yum源配置及yum
Android學習心得(二)
Android儲存方式 儲存偏好設定 持久化資料:使應用程式執行時需要長期儲存一些資料。 SharePreferences物件、檔案和 SQLite資料庫來儲存這些持久化資料 存取活動的偏好設定 SharePreferences類屬於Android.cntent
python學習2(轉載)
一、流程控制之while迴圈 語法:while 條件: 迴圈體else: else語句(當條件不成立的時候執行這裡 和break沒關係) 判斷條件是否成立。 如果成立執行迴圈體。然後再次判斷條件,。。。。。直到條件不成立的時候跳出迴圈 break :終止當前本層迴圈(直接跳到迴圈的末尾)
Java開發學習心得(一):SSM環境搭建
Java開發學習心得(一):SSM環境搭建 有一點.NET的開發基礎,在學校學過基礎語法,對JAVA有點興趣,就簡單學習了一下,記錄一下從哪些方面入手的,暫時不打算深入到原理方面,先簡單搭下環境看看,所以有些地方可能講得不慎準確。 1 SSM框架 從網上的討論來看,SSM框架似乎正在慢慢被Spring
python學習3(轉載)
主要內容: 列表 和 元組和字典 列表 一、列表介紹 列表是一種能儲存大量資料的資料結構,是能裝物件的物件。由方括號 [] 括起來,能放任意型別的資料,資料之間用逗號隔開 列表儲存資料是有順序的 二、增刪改查 lis = [] 1、增加 (三種) lis.append() &nb
Java開發學習心得(二):Mybatis和Url路由
rac 處理 2.4 報錯 localhost insert 實體 tips control Java開發學習心得(二):Mybatis和Url路由 序號接上一篇Java開發學習心得(一):SSM環境搭建 1.3 Mybatis MyBatis 本是apache的一個開源項