(轉)ElasticSearch學習

(二期)2一、全文搜索引擎Elasticsearch

【課程21】elasticsearch.xmind82.1KBhtml

【課程21】lucene.xmind0.8MBjava

【課程21】基本用法....api.xmind83.2KBnode

【課程21預習】全...arch.xmind0.4MBreact

 

Lucene

爲了更深刻地理解ElasticSearch的工做原理,特別是索引和查詢這兩個過程,理解Lucene的工做原理相當重要。本質上,ElasticSearch是用Lucene來實現索引的查詢功能的。linux

 

lucene的最新發布版本(7.5.0)git

創建索引概念

 

爲了對文檔進行索引,Lucene 提供了五個基礎的類,他們分別是 Document, Field, IndexWriter, Analyzer, Directory。下面咱們分別介紹一下這五個類的用途:github

 

Documentspring

Document 是用來描述文檔的,這裏的文檔能夠指一個 HTML 頁面,一封電子郵件,或者是一個文本文件。一個 Document 對象由多個 Field 對象組成的。能夠把一個 Document 對象想象成數據庫中的一個記錄,而每一個 Field 對象就是記錄的一個字段。sql

Field數據庫

Field 對象是用來描述一個文檔的某個屬性的,好比一封電子郵件的標題和內容能夠用兩個 Field 對象分別描述。

Analyzer

在一個文檔被索引以前,首先須要對文檔內容進行分詞處理,這部分工做就是由 Analyzer 來作的。Analyzer 類是一個抽象類,它有多個實現。針對不一樣的語言和應用須要選擇適合的 Analyzer。Analyzer 把分詞後的內容交給 IndexWriter 來創建索引。

IndexWriter

IndexWriter 是 Lucene 用來建立索引的一個核心的類,他的做用是把一個個的 Document 對象加到索引中來。

Directory

這個類表明了 Lucene 的索引的存儲的位置,這是一個抽象類,它目前有兩個實現,第一個是 FSDirectory,它表示一個存儲在文件系統中的索引的位置。第二個是 RAMDirectory,它表示一個存儲在內存當中的索引的位置。

搜索文檔概念

Lucene 提供了幾個基礎的類來完成這個過程,它們分別是呢 IndexSearcher, Term, Query, TermQuery, Hits. 下面咱們分別介紹這幾個類的功能。

 

Query

這是一個抽象類,他有多個實現,好比 TermQuery, BooleanQuery, PrefixQuery. 這個類的目的是把用戶輸入的查詢字符串封裝成 Lucene 可以識別的 Query。

Term

Term 是搜索的基本單位,一個 Term 對象有兩個 String 類型的域組成。生成一個 Term 對象能夠有以下一條語句來完成:Term term = new Term(「fieldName」,」queryWord」); 其中第一個參數表明了要在文檔的哪個 Field 上進行查找,第二個參數表明了要查詢的關鍵詞。

TermQuery

TermQuery 是抽象類 Query 的一個子類,它同時也是 Lucene 支持的最爲基本的一個查詢類。生成一個 TermQuery 對象由以下語句完成: TermQuery termQuery = new TermQuery(new Term(「fieldName」,」queryWord」)); 它的構造函數只接受一個參數,那就是一個 Term 對象。

IndexSearcher

IndexSearcher 是用來在創建好的索引上進行搜索的。它只能以只讀的方式打開一個索引,因此能夠有多個 IndexSearcher 的實例在一個索引上進行操做。

Hits

Hits 是用來保存搜索的結果的。

 

倒排索引

倒排索引(Inverted Index)是一種索引數據結構。在倒排索引中,詞語被映射到包含該詞語的文檔。

 

倒排索引源於實際應用中須要根據屬性的值來查找記錄。

這種索引表中的每一項都包括一個屬性值和具備該屬性值的各記錄的地址。

因爲不是由記錄來肯定屬性值,而是由屬性值來肯定記錄的位置,於是稱爲倒排索引(inverted index)。

 

好比:正常關鍵字對應關係應該是:「文章號」對「文章中全部關鍵詞」。倒排索引把這個關係倒過來,變成: 「關鍵詞」對「擁有該關鍵詞的全部文章號」。

 

經過使用倒排索引,能夠實現快速的全文搜索。一個簡單的倒排索引及其構建過程以下圖所示,其中文檔d1和d2的內容分別是「home sales rise in July」和「increase in home sales in July」。

 

對於文檔d1和d2,首先進行分詞處理,將文本內容劃分爲詞語集。由於在英文文本中,單詞之間均有空格,因此使用空格做爲分隔符進行分詞處理,獲得詞語集,如圖中左側一列。對於劃分後的詞語集,進行統計,統計詞語及其出現的次數和位置,如圖中右側一列,構成倒排索引。

 

關鍵詞 文章號[出現頻率] 出現位置   

(倒排索引及其構建過程)

  • 實現時,lucene將上面三列分別做爲詞典文件(Term Dictionary)、頻率文件(frequencies)、位置文件 (positions)保存。其中詞典文件不只保存有每一個關鍵詞,還保留了指向頻率文件和位置文件的指針,經過指針能夠找到該關鍵字的頻率信息和位置信息。 
  • 索引時,假設要查詢單詞 「live」,lucene先對詞典二元查找、找到該詞,經過指向頻率文件的指針讀出全部文章號,而後返回結果。詞典一般很是小,於是,整個過程的時間是毫秒級的

 

 

項目包分析
  • Package: org.apache.lucene.document

這個包提供了一些爲封裝要索引的文檔所須要的類,好比 Document, Field。這樣,每個文檔最終被封裝成了一個 Document 對象。

  • Package: org.apache.lucene.analysis

這個包主要功能是對文檔進行分詞,由於文檔在創建索引以前必需要進行分詞,因此這個包的做用能夠當作是爲創建索引作準備工做。

  • Package: org.apache.lucene.index

這個包提供了一些類來協助建立索引以及對建立好的索引進行更新。這裏面有兩個基礎的類:IndexWriter 和 IndexReader,其中 IndexWriter 是用來建立索引並添加文檔到索引中的,IndexReader 是用來刪除索引中的文檔的。

  • Package: org.apache.lucene.search

這個包提供了對在創建好的索引上進行搜索所須要的類。好比 IndexSearcher 和 Hits, IndexSearcher 定義了在指定的索引上進行搜索的方法,Hits 用來保存搜索獲得的結果。

  • org.apache.lucene.queryParser

包含了用於構建、解析查詢條件的類。

  • org.apache.lucene.store包

包含了用於存儲索引的類。

 

時序圖(流程圖)

見代碼

 

索引與查詢

索引過程:Lucene用用戶指定好的analyzer解析用戶添加的Document。固然Document中不一樣的Field能夠指定不一樣的analyzer。若是用戶的Document中有title和description兩個Field,那麼這兩個Field能夠指定不一樣的analyzer。

 

搜索過程:用戶的輸入查詢語句將被選定的查詢解析器(query parser)所解析,生成多個Query對象。固然用戶也能夠選擇不解析查詢語句,使查詢語句保留原始的狀態。在ElasticSearch中,有的Query對象會被解析(analyzed),有的不會,好比:前綴查詢(prefix query)就不會被解析,精確匹配查詢(match query)就會被解析。對用戶來講,理解這一點相當重要。

 

對於索引過程和搜索過程的數據解析這一環節,咱們須要把握的重點在於:倒排索引中詞應該和查詢語句中的詞正確匹配。

流程
  • Lucene的analysis模塊主要負責詞法分析及語言處理而造成Term。
  • Lucene的index模塊主要負責索引的建立,裏面有IndexWriter。
  • Lucene的store模塊主要負責索引的讀寫。
  • Lucene的QueryParser主要負責語法分析。
  • Lucene的search模塊主要負責對索引的搜索。
  • Lucene的similarity模塊主要負責對相關性打分的實現。

在Lucene的倒排索引中,包含字段(Field)、文檔(Document)、關鍵字(Term)這三個部分。每個關鍵字均與一個集合相映射。集合中的每個元素爲一個二元組(Document,Field),表示該文檔的該字段包含此關鍵字。Lucene的工做原理如圖所示,主要分爲如下6個步驟:

  • 1)爲每個待檢索的文件構建Document類對象,將文件中各部份內容做爲Field類對象。
  • 2)使用Analyzer類實現對文檔中的天然語言文本進行分詞處理,並使用IndexWriter類構建索引。
  • 3)使用FSDirectory類設定索引存儲的方式和位置,實現索引的存儲。
  • 4)使用IndexReader類讀取索引。
  • 5)使用Term類表示用戶所查找的關鍵字以及關鍵字所在的字段,使用QueryParser類表示用戶的查詢條件。
  • 6)使用IndexSearcher類檢索索引,返回符合查詢條件的Document類對象。
查詢語言

用戶使用Lucene進行查詢操做時,輸入的查詢語句會被分解成一個或者多個Term以及邏輯運算符號。一個Term,在Lucene中能夠是一個詞,也能夠是一個短語(用雙引號括引來的多個詞)。若是事先設定規則:解析查詢語句,那麼指定的analyzer就會用來處理查詢語句的每一個term造成Query對象。

 

一個Query對象中會存在多個布爾運算符,這些布爾運算符將多個Term關聯起來造成查詢子句。

可視化工具Luke

(我用這個)

Hibernate Search回顧

回顧以前的課程內容。詳細內容能夠回顧以前的課程12的內容、開源博客項目mblog解讀,其中使用到了Hibernate Search。

經過hibernate search 建立 lucene全文索引。

Hibernate Search是在apache Lucene的基礎上創建的主要用於Hibernate的持久化模型的全文檢索工具。像Lucene這樣的檢索引擎可以給咱們的項目在進行檢索的時候帶來很是高的效率,可是它們在基本對象的檢索時會有一些問題,好比不能實現檢索內容跟實體的轉換,Hibernate Search正是在這樣的狀況下發展起來的,基於對象的檢索引擎,可以很方便的將檢索出來的內容轉換爲具體的實體對象。此外Hibernate Search可以根據須要進行同步或異步的索引更新。

 

Hibernate Search是 hibernate 對著名的全文檢索系統 Lucene 的一個集成方案,做用在於對數據表中某些內容龐大的字段(如聲明爲text的字段)創建全文索引,它這樣經過hibernate search就能夠對這些字段進行全文檢索後得到相應的POJO,從而加快了對內容龐大字段進行模糊搜索的速度(sql語句中like匹配)。

原理:

Hibernate Search是給Hibernate持久化模型架構來使用的一套全文檢索工具,其全文檢索依賴於Lucence引擎。全文搜索引擎(lucence)會將你要查詢的這個字段的詞語,進行分詞,直接匹配分詞。

運行原理

一、構造LuceneQuery查詢索引庫 

二、EntityManager 構造 FullTextEntityManager 查詢數據庫 

三、合併EntityManager 和 LuceneQuery —– FullTextQuery 查詢索引庫和數據庫 

四、查詢索引庫 fullTextQuery.getResultSize(); 查詢索引,去重id 

五、查詢數據庫 fullTextQuery.getResultList(); 根據索引庫返回 id ,查詢數據庫

Elasticsearch
  • 簡單內容的演示,先作好一個postman的數據演示例子
  • 一個簡單例子(同postman請求例子)
  • 一個複雜例子
簡介

Elasticsearch是一個基於Apache Lucene(TM)的開源搜索引擎。不管在開源仍是專有領域,Lucene能夠被認爲是迄今爲止最早進、性能最好的、功能最全的搜索引擎庫。

 

可是,Lucene只是一個庫。想要使用它,你必須使用Java來做爲開發語言並將其直接集成到你的應用中,更糟糕的是,Lucene很是複雜,你須要深刻了解檢索的相關知識來理解它是如何工做的。

 

Elasticsearch也使用Java開發並使用Lucene做爲其核心來實現全部索引和搜索的功能,可是它的目的是經過簡單的RESTful API來隱藏Lucene的複雜性,從而讓全文搜索變得簡單。

基本概念

索引

  • 含有相同屬性的文檔集合

文檔

  • 文檔是能夠被索引的基本數據單位

文檔類型

  • 索引能夠定義一個或多個類型,文檔必須屬於一個類型

節點

集羣

分片索引

  • 每一個索引都有多個分片,每一個分片是一個lucene索引。
  • 因爲單個節點因爲物理機硬件限制,存儲的文檔是有限的,若是一個索引包含海量文檔,則不能在單個節點存儲。ES提供分        片機制,同一個索引能夠存儲在不一樣分片(數據容器)中,這些分片又能夠存儲在集羣中不一樣節點上

備份

  • 拷貝一份分片就完成了分片的備份

索引副本

時間之門

 

特色
  • 開箱即用。安裝好ElasticSearch後,全部參數的默認值都自動進行了比較合理的設置,基本不須要額外的調整。包括內置的發現機制(好比Field類型的自動匹配)和自動化參數配置。
  • 天生集羣。ElasticSearch默認工做在集羣模式下。節點都將視爲集羣的一部分,並且在啓動的過程當中自動鏈接到集羣中。
  • 自動容錯。ElasticSearch經過P2P網絡進行通訊,這種工做方式消除了單點故障。節點自動鏈接到集羣中的其它機器,自動進行數據交換及以節點之間相互監控。索引分片
  • 擴展性強。不管是處理能力和數據容量上均可以經過一種簡單的方式實現擴展,即增添新的節點。
  • 近實時搜索和版本控制。因爲ElasticSearch天生支持分佈式,因此延遲和不一樣節點上數據的短暫性不一致無可避免。ElasticSearch經過版本控制(versioning)的機制儘可能減小問題的出現。
工做原理
應用場景
  • 海量數據分析引擎
  • 站內搜索引擎
  • 數據倉庫
安裝

下載linux版本,並解壓。

 

cd elasticsearch-6.4.3
#啓動
./bin/elasticsearch

默認端口9200。

 

  • 單例安裝

root權限下直接運行elasticsearch會報錯,因此須要切換到其餘用戶。

 

#新增一個用戶
useradd lfq
#受權
chown -R lfq /opt/elasticsearch-*
#切換到這個用戶
su lfq

安裝過程當中可能會遇到如下兩個錯誤:

一、[1]: max file descriptors [65535] for elasticsearch process is too low, increase to at least [65536]

 

文件描述符過低

解決辦法:

切換到root用戶修改/etc/security/limits.conf

su root
vim /etc/security/limits.conf

文本末加入

* soft nofile 65536
* hard nofile 131072
* soft nproc 2048
* hard nproc 4096 

推出當前用戶,重新進入

如今ok了~

 

二、[2]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

max_map_count 的值是指一個進程最多可用於的內存映射區(memory map areas),在調用malloc會用到,由mmap/mprotect生成。

解決辦法:

切換到root用戶修改配置/etc/sysctl.conf

su root
vim /etc/sysctl.conf

加入

vm.max_map_count=655360

而後使其生效

sysctl -p

ok,能夠了。

 

三、有時候啓動elasticsearch時候會提示內存不足,而後啓動不了,這時候能夠改小jvm最小內存

cat config/jvm.options
 
  
-Xms1g 改爲 -Xms512m

 

若是須要外網訪問,能夠添加外網的ip。如今測試環境容許全部人訪問~~

vim config/elasticsearch.yml 
#添加下面一行便可
network.host: 0.0.0.0
#容許跨域訪問,方便後面可視化工具elasticsearch-head 
http.cors.enabled: true
http.cors.allow-origin: "*"

 

啓動完畢以後,打開瀏覽器輸入連接:

 

  • 分佈式安裝

主節點配置

vim config/elasticsearch.yml
#添加一下配置
cluster.name: kobe
node.name: master
node.master: true

重啓服務。

 

從節點1

重新解壓一份到slave1文件夾

vim config/elasticsearch.yml
 
  
cluster.name: kobe
node.name: slave1
http.port: 9800
network.host: 0.0.0.0
#設置主動發現主節點地址
discovery.zen.ping.unicast.hosts: ["127.0.0.1"]

若是提示id重複,刪除slave1文件夾下的data文件夾下的節點數據,而後重啓便可

 

  • elasticsearch-head安裝

elasticsearch-head 是用於監控 Elasticsearch 狀態的客戶端插件,包括數據可視化、執行增刪改查操做等。elasticsearch-head 插件的安裝在 Linux 和 Windows 沒什麼區別,安裝以前確保當前系統已經安裝 nodejs 便可。

git clone git://github.com/mobz/elasticsearch-head.git
cd elasticsearch-head
npm install  或者cnpm install(須要安裝淘寶鏡像)
npm run start
 
  
打開瀏覽器 http://localhost:9100/

至此,elasticsearch-head連上elasticsearch了。

 

集羣狀態解讀

head插件會以不一樣的顏色顯示。 

1. 綠色——最健康的狀態,表明全部的主分片和副本分片均可用; 

2. 黃色——全部的主分片可用,可是部分副本分片不可用; 

3. 紅色——部分主分片不可用。(此時執行查詢部分數據仍然能夠查到,遇到這種狀況,仍是趕快解決比較好。)

 

若是集羣狀態爲紅色,Head插件顯示:集羣健康值red。則說明:至少一個主分片分配失敗。這將致使一些數據以及索引的某些部分再也不可用。 

儘管如此, ElasticSearch仍是容許咱們執行查詢,至因而通知用戶查詢結果可能不完整仍是掛起查詢,則由應用構建者來決定。

基本用法-restful api

管理功能

  • i:檢查集羣、節點、索引的狀態以及相關的統計數據
  • ii:管理集羣、節點、索引數據以及源數據

維護索引

  • i:基本操做。 
  • 提供針對索引的CRUD操做(Create【PUT】, Read【GET】, Update【POST】, and Delete【POST】)
  • ii:高級操做 
  • 以及其餘如分頁、排序、過濾等高級操做

 

檢查集羣狀態

curl localhost:9200/_cat/health?v

檢查節點狀態

curl localhost:9200/_cat/nodes?v

查詢所有索引

curl localhost:9200/_cat/indices?v

 

適合舊版本的,新版本看postman

https://www.do1618.com/archives/1276/elasticsearch-%E4%B8%AD%E7%9A%84%E7%B4%A2%E5%BC%95%E4%B8%8E%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%89%8D%E7%94%9F%E4%BB%8A%E4%B8%96/

 

建立索引

curl -XPUT localhost:9200/索引名/類型/id -d {//JSON格式的body體}

刪除索引

curl -XDELETE localhost:9200/索引名

查詢索引

curl -XGET localhost:9200/索引名/類型/id
#其中 q=  表示匹配索引中指定數據
curl -XGET localhost:9200/索引名/_search?q=

 

_bulk 批量操做
_search 搜索
?pretty 表示格式化輸出
  • mapping-結構化映射關係。爲空時候是非結構化索引

詳細請看postman~~~,請用postman導入如下json數據練習!

 

elasticsearch-test.post...tion.json9.9KB

 

高級查詢

簡單查詢

條件查詢

聚合查詢

springboot集成ES

集成配置:

  • 初始化TransportClient
  • InetSocketTransportAddress節點信息node
  • TransportClient中添加階段信息,集羣能夠添加多個節點。
  • 設置集羣配置Setting,包括cluster.name等信息

使用:

TransportClient client;

 

項目應用開發指南
開發指南
  • 第一步:索引結構設計

首先須要考慮搜索的內容主體包含的信息,如ID,標題、摘要、做者等。還須要包括排序信息(更新時間,建立時間),或須要搜索的字段等信息。

  • 第二步:爲索引結構創建對應的模板(DTO),字段應該與索引的字段一一對應。另外,由於key的名字都是定死的,爲了統一管理,能夠給每一個key定義成final,方便統一管理和getset等。
  • 第三步:建立searchService,主要有個兩個方法,一、構建索引(建立、更新),二、刪除索引。
  • 構建索引邏輯:
  • 首先要一個ID做爲惟一要構建的索引。經過ID從數據庫中查詢信息出來,包括須要關聯的表等信息,獲得模板數據(DTO),而後去elasticsearch查詢有沒該索引,若是沒有則建立,若是有一條就更新,若是有多條就全刪除而後從新建立。
  • 考慮到一些elasticsearch有不穩定的時候,因此能夠給構建索引、刪除索引創建一個重試機制,好比3次重試機會。
  • 第四步:當業務數據發生變化時候更新對應索引信息,分爲兩種形式調用
  • 同步調用:直接在業務方法重點調用searchService對應的方法。
  • 異步調用:基於消息中間件,如kafka,rabbitmq等。
  • 第五步:編寫搜索業務。
  • 當用戶沒輸入關鍵字的時候,默認直接從數據庫查詢信息。
  • 當用戶輸入關鍵字的時候先從elasticsearch條件查詢出數據的IDs,而後拿IDs去從數據庫中取。
複雜查詢
     * 使用QueryBuilder
     * termQuery("key", obj) 徹底匹配
     * termsQuery("key", obj1, obj2..)   一次匹配多個值
     * matchQuery("key", Obj) 單個匹配, field不支持通配符, 前綴具高級特性
     * multiMatchQuery("text", "field1", "field2"..); 匹配多個字段, field有通配符忒行
     * matchAllQuery();         匹配全部文件
     

 

          * 組合查詢
     * must(QueryBuilders) :   AND
     * mustNot(QueryBuilders): NOT
     * should:                  : OR
 
  

 

  * 只查詢一個id的
     * QueryBuilders.idsQuery(String...type).ids(Collection<String> ids)

 

   /**
     * moreLikeThisQuery: 實現基於內容推薦, 支持實現一句話類似文章查詢
     * {   
        "more_like_this" : {   
        "fields" : ["title", "content"], // 要匹配的字段, 不填默認_all
        "like_text" : "text like this one", // 匹配的文本
        }   
    }     
    
    percent_terms_to_match:匹配項(term)的百分比,默認是0.3
 
  
    min_term_freq:一篇文檔中一個詞語至少出現次數,小於這個值的詞將被忽略,默認是2
    
    max_query_terms:一條查詢語句中容許最多查詢詞語的個數,默認是25
    
    stop_words:設置中止詞,匹配時會忽略中止詞
    
    min_doc_freq:一個詞語最少在多少篇文檔中出現,小於這個值的詞會將被忽略,默認是無限制
    
    max_doc_freq:一個詞語最多在多少篇文檔中出現,大於這個值的詞會將被忽略,默認是無限制
    
    min_word_len:最小的詞語長度,默認是0
    
    max_word_len:最多的詞語長度,默認無限制
    
    boost_terms:設置詞語權重,默認是1
    
    boost:設置查詢權重,默認是1
    
    analyzer:設置使用的分詞器,默認是使用該字段指定的分詞器
     */

 

/**
     * 前綴查詢
     */
    @Test
    public void testPrefixQuery() {
        QueryBuilder queryBuilder = QueryBuilders.matchQuery("user", "kimchy");
        searchFunction(queryBuilder);
    }

 

分詞

 

 

相關文章
相關標籤/搜索