主頁 > 後端開發 > 搜索引擎springboot集成(elasticSearch)

搜索引擎springboot集成(elasticSearch)

2021-02-12 05:55:38 後端開發

各位小伙伴們,今天是今年的最后一天,這是我今年的最后一篇博客,在這里祝大家新年快樂!本次講的是近幾年比較流行的search搜索引擎,本文寫的比較粗略,希望大家看了會有所識訓,如若寫錯,請在評論區指出,我感激不盡!

1 搜索引擎springboot集成(elasticSearch)

1.1 為什么要使用ElasticSearch

? 實際專案中,我們建立一個網站或應用程式,并要添加搜索功能,令我們受打擊的是:搜索作業是很難的,我們希望我們的搜索解決方案要快,我們希望有一個零配置和一個完全免費的搜索模式,我們希望能夠簡單地使用JSON/XML通過HTTP的索引資料,我們希望我們的搜索服務器始終可用,我們希望能夠從一臺開始并在需要擴容時方便地擴展到數百,我們要實時搜索,我們要簡單的多租戶,我們希望建立一個云的解決方案,

? 雖然全文搜索領域,Lucene可以被認為是迄今為止最先進、性能最好的、功能最全的搜索引擎庫,但是,Lucene只是一個庫,想要使用它,你必須使用Java來作為開發語言并將其直接集成到你的應用中,更糟糕的是,Lucene的配置及使用非常復雜,你需要深入了解檢索的相關知識來理解它是如何作業的,

1.2 ElasticSearch(簡稱ES)

? ES即為了解決原生Lucene使用的不足,優化Lucene的呼叫方式,并實作了高可用的分布式集群的搜索方案,其第一個版本于2010年2月出現在GitHub上并迅速成為最受歡迎的專案之一,

? 首先,ES的索引庫管理支持依然是基于Apache Lucene?的開源搜索引擎,ES也使用Java開發并使用Lucene作為其核心來實作所有索引和搜索的功能,但是它的目的是通過簡單的 RESTful API來隱藏Lucene的復雜性,從而讓全文搜索變得簡單,Lucene直接通過java API呼叫,而ES把這些API呼叫程序進行了的封裝為簡單RESTful請求,讓我們呼叫起來更加簡單.

? 不過,ES的核心不在于Lucene,其特點更多的體現為:分布式的實時檔案存盤,每個欄位都被索引并可被搜索,分布式的實時分析搜索引擎,可以擴展到上百臺服務器,處理PB級結構化或非結構化資料,高度集成化的服務,你的應用可以通過簡單的 RESTful API、各種語言的客戶端甚至命令列與之互動,上手Elasticsearch非常容易,它提供了許多合理的預設值,并對初學者隱藏了復雜的搜索引擎理論,它擁有開瓶即飲的效果(安裝即可使用),只需很少的學習既可在生產環境中使用,

? Lucene和ES聯系,區別:專案中為啥使用ES而不用Lucene.

? 聯系:ElasticSearch封裝了Lucene,讓使用變得更簡單,在高可用上面做得更好,

? 區別:ElasticSearch除了擁有Lucene所有優點以外,還擁有自己優點.

? 可用性:支持集群沒有單點故障

? 擴展性:支持集群擴展

? 一般lucene在中小型專案中使用(但是也能使用es),而ES在大型專案中使用.因為ES支持在集群環境使用,并且自身也支持集群.

2 ES安裝及使用說明

官網地址=>https://www.elastic.co/cn/elasticsearch

自行搜索

3 ES資料管理

3.1 什么是ES中的檔案

ES是面向檔案(document oriented)的,這意味著它可以存盤整個物件或檔案(document),然而它不僅僅是存盤,還會索引(index,創建索引)每個檔案的內容使之可以被搜索,在ES中,你可以對檔案(而非成行成列的資料)進行索引、搜索、排序、過濾,

ES使用Javascript物件符號(JavaScript Object Notation),也就是JSON,作為檔案序列化格式,JSON現在已經被大多語言所支持,而且已經成為NoSQL領域的標準格式,

ES存盤的一個員工檔案的格式示例:

{
“email”: “[email protected]”,

“name”: “文兵”,

“info”: {
“addr”: “四川省成都市”,

“age”: 30,

“interests”: [ “櫻桃”, “粉嫩” ]

},

“join_date”: “2014-06-01”

}

盡管原始的 employee物件很復雜,但它的結構和物件的含義已經被完整的體現在JSON中了,在ES中將物件轉化為JSON并做索引要比在表結構中做相同的事情簡單的多,

一個檔案不只有資料,它還包含元資料(metadata)—關于檔案的資訊,三個必須的元資料節點是:

節點 說明
_index 索引庫,檔案存盤的地方
_type 檔案型別(6.x之后取消掉了這個屬性)
_id 檔案的唯一標識

_index:索引庫,類似于關系型資料庫里的“資料庫”—它是我們存盤和索引關聯資料的地方,

_type:型別,類似于關系型資料庫中表.在應用中,我們使用物件表示一些“事物”,例如一個用戶、一篇博客、一個評論,或者一封郵件,可以是大寫或小寫,不能包含下劃線或逗號,我們將使用 employee 做為型別名,

_id: 與 _index 和 _type 組合時,就可以在ELasticsearch中唯一標識一個檔案,當創建一個檔案,你可以自定義 _id ,也可以讓Elasticsearch幫你自動生成,

另外還包括:_uid 檔案唯一標識(_type#_id)

_source:檔案原始資料

_all:所有欄位的連接字串

3.2 檔案的增刪改

? 我們以員工物件為例,我們首先要做的是存盤員工資料,每個檔案代表一個員工,在ES中存盤資料的行為就叫做索引(indexing),檔案歸屬于一種型別(type),而這些型別存在于索引(index)中,我們可以簡單的對比傳統資料庫和ES的對應關系:

關系資料庫(MYSQL) -> 資料庫DB-> 表TABLE-> 行ROW-> 列Column

Elasticsearch -> 索引庫Indices -> 型別Types -> 檔案Documents -> 欄位Fields

ES集群可以包含多個索引(indices)(資料庫),每一個索引庫中可以包含多個型別(types)(表),每一個型別包含多個檔案(documents)(行),然后每個檔案包含多個欄位(Fields)(列),

創建索引檔案

使用自己的ID創建

PUT {index}/{type}/{id}
{
  "field": "value",
  ...
}

使用內置ID創建

POST {index}/{type}
{
  "field": "value",
  ...
}

獲取指定ID的檔案

GET itsource/employee/123

更新檔案

PUT {index}/{type}/{id}
{
  "field": "value",
  ...
}

跟創建語法一樣,但是會改變版本號

洗掉檔案

DELETE {index}/{type}/{id}

注意:盡管檔案不存在,但_version依舊增加了,這是內部記錄的一部分,它確保在多節點間不同操作可以有正確的順序

put和post是差不多的,都可以用來修改和添加,唯一區別就是,在添加時put需要手動給id而post不需要賦id,系統自動給個隨機id

3.3 檔案的簡單查詢(searchAPI)

GET /_search
GET /woniu47/_search
GET /woniu47,woniu48/_search
GET /woniu*/_search

URLsearch:

通過ID獲取

GET /woniu47/_doc/1

只回傳檔案內容,不要元資料:

GET /woniu47/_doc/1/_source

查詢字串搜索:

回傳檔案的部分欄位:

GET /woniu47/_doc/1?_source=name,age

查詢年齡為25歲的學員

GET /woniu47/_search?q=age:25

組合查詢:

組合查詢:

+表示并且,多個條件做且運算====>MUST

空格表示或,多個條件做或運算====>SHOULD

-表示非,多個條件做非運算====>MUST_NOT

+name:john +tweet:mary

+name:(mary john) +date:>2014-09-10 +(aggregations geo)

age[20 TO 30]

查詢年齡在25到28 (兩邊都包括)或則姓名為wangwu的學員

GET /woniu47/_search?q=age:>=25 +age<=28 name:wangwu

GET /woniu47/_search?q=age[25 TO 28] name:wangwu

中括號可以換成大括號,中括號有=大括號沒有

分頁:

查詢20歲以上的學員,顯示3條

GET /woniu47/_search?q=age:>=20&size=3

查詢20歲以上的學員,每頁顯示3條,顯示第2頁

GET /woniu47/_search?q=age:>=20&size=3&from=3

查詢引數說明:

Name Description
q 標識查詢字串
df 在查詢中,沒有定義欄位前綴的情況下默認欄位的前綴
analyzer 在分析查詢字串時,分析器的名字
default_operator 被用到的默認操作,有AND和OR兩種,默認是OR
explain 對于每一個命中,對怎樣得到命中得分的計算給出一個解釋
_source 將其設定為false,查詢就會放棄檢索_source欄位,也可以通過設定檢索部分檔案
fields 標識查詢字串
sort 排序執行,可以fieldName、fieldName:asc
track_scores 當排序的時候,將其設定為true,可以回傳相關度得分
from 分頁查詢起始點,默認0
size 查詢數量,默認10
search_type 搜索操作執行的型別

4 索引與分詞

4.1 什么是倒排索引

? 倒排索引是先將檔案進行分詞處理,標記每個詞都出現在哪些檔案里面,這樣就可以快速查詢某個詞所出現的檔案位置,與之對應的是“正排索引”,例如我們看一本書的目錄,從前往后查找目錄,就是正排索引,

? 我們先來看3組檔案,我們將檔案編號分別列為1、2、3,

https://img-blog.csdnimg.cn/img_convert/23778d72d45fcf1d7532e55f1baba182.png

這3個檔案里,核心詞是“衛生間隔斷”,如果你在搜索引擎上,直接搜索衛生間隔斷,拋開文章內容,單看標題,哪個排第一?沒錯,就是檔案1會出現在第一位,為什么?

因為倒排索引里,會通過單詞詞典,統計一個單詞在檔案里出現的位置,我們將上述檔案里出現的詞,都賦予一個ID,

? 這是一個最簡單的倒排索引示意圖:

4.2 什么是分詞

分詞是指將文本轉換成一系列單詞的程序,也可以叫文本分析,在es里面稱為Analysis,如下圖所示:

分詞器是ES中專門處理分詞的組件,英文為Analyzer,它的組成如下:

  • Character Filters

針對原始文本進行處理,比如去除html特殊標記

  • Tokenizer

將原始文本按照一定規則切分為單詞

  • Token Filters

針對tokenizer處理的單詞進行再加工,比如轉小寫、洗掉或新增等處理

4.3 Analyze API

ES提供了一個測驗分詞的api介面,方便驗證分詞效果,endpoint是_analyze

直接指定analyzer進行測驗

POST _analyze
{
  "analyzer": "standard",
  "text": "hello world"
}

直接指定索引中的欄位進行測驗

POST woniu47/_analyze
{
  "field": "name",
  "text": "hello java"
}

ES自帶分詞器如下:

Name Description
standard 默認分詞器,按詞切分,支持多語言,小寫處理
simple 按照非字母切分,小寫處理
whitespace 按照空格切分
stop 相比simple 多了stop word處理(語氣2組詞等修飾性的詞語,比如the、an、的、這等等)
keyword 不分詞,直接將輸入作為一個單詞輸出
pattern 通過正則運算式自定義分割符,默認是\W+, 即非字詞的符號作為分隔符

4.4 中文分詞器

中文分詞器是將一個漢字序列切分成一個一個單獨的詞,在英語中,單詞之間是以空格作為自然分界符,漢語中詞沒有一個形式上的分界符,背景關系不同,分詞結果迥異,比如交叉歧義問題,比如下面兩種分詞都合理:

  • 乒乓球拍/賣/完了
  • 乒乓球/拍賣/完了
    常用分詞系統

1.IK

  1. 實作中英文單詞的切分,支持ik_smart、ik_maxword等模式,

  2. 可自定義詞庫,支持熱更新分詞詞典

  3. https://github.com/medcl/elasticsearch-analysis-ik

2.jieba

python中最流行的分詞系統,支持分詞和詞性標注
支持繁體分詞、自定義詞典、并行分詞等
https://github.com/sing1ee/elasticsearch-jieba-plugin
IK的使用

1.安裝

  1. git clone https://github.com/medcl/elasticsearch-analysis-ik
  2. cd elasticsearch-analysis-ik
  3. mvn clean
  4. mvn compile
  5. mvn package
  6. 拷貝和解壓release下的檔案: #{project_path}/elasticsearch-analysis-ik/target/releases/elasticsearch-analysis-ik-*.zip 到你的 elasticsearch 插件目錄, 如: plugins/ik 重啟elasticsearch
    2.測驗
POST _analyze
{
  "analyzer": "ik_smart",
  "text": "中華人民共和國國歌"
}
POST _analyze
{
  "analyzer": "ik_max_word",
  "text": "中華人民共和國國歌"
}

3.ik_smart與ik_max_word的區別

ik_max_word: 會將文本做最細粒度的拆分,比如會將“中華人民共和國國歌”拆分為“中華人民共和國,中華人民,中華,華人,人民共和國,人民,人,民,共和國,共和,和,國國,國歌”,會窮盡各種可能的組合,適合 Term Query;

ik_smart: 會做最粗粒度的拆分,比如會將“中華人民共和國國歌”拆分為“中華人民共和國,國歌”,適合 Phrase 查詢

注意: 在config檔案夾下面有很多擴展詞的配置

5 Mapping(檔案映射)

ES的檔案映射(mapping)機制用于進行欄位型別確認(欄位是什么型別,什么分詞器),將每個欄位匹配為一種確定的資料型別,類似于資料庫的表結構定義,主要作用如下:

定義Index下的欄位名(Field Name)
定義欄位的型別,比如數值型、字串型、布爾型等
定義倒排索引相關配置,比如是否索引、記錄position等
查看某個Index的Mapping

GET woniu47/_mapping

5.1 自定義Mapping

創建一個Index的映射

PUT woniu48
{
  "mappings": {
    "properties": {
      "name": {
        "type": "keyword"
      },
      "age": {
        "type": "integer"
      },
      "desc": {
        "type": "text",
        "analyzer": "ik_smart"
      }
    }
  }
}

Mapping中的欄位型別一旦設定后,禁止直接修改,因為Lucene實作的倒排索引生成后不允許修改

通過dynamic引數來控制欄位的新增
true(默認)允許自動新增欄位
false 不允許自動新增欄位,但是檔案可以正常寫入,但無法對欄位進行查詢等操作
strict 檔案不能寫入,報錯

PUT woniu48
{
  "mappings": {
    "dynamic": "false",
    "properties": {
      "name": {
        "type": "keyword"
      },
      "age": {
        "type": "integer"
      },
      "desc": {
        "type": "text",
        "analyzer": "ik_smart"
      }
    }
  }
}

copy_to

  • 將該欄位的值復制到目標欄位,實作類似_all的作用
    不會出現在_source中,只用來搜索
PUT woniu48
{
  "mappings": {
    "dynamic": "false",
    "properties": {
      "name": {
        "type": "keyword",
        "copy_to": "full_name"
      },
      "age": {
        "type": "integer"
      },
      "desc": {
        "type": "text",
        "analyzer": "ik_smart",
        "copy_to": "full_name"
      },
      "full_name": {
        "type": "text"
      }
    }
  }
}

index

  • 控制當前欄位是否索引,默認為true,即記錄索引,false不記錄,即不可搜索
PUT woniu48
{
  "mappings": {
    "dynamic": "false",
    "properties": {
      "name": {
        "type": "keyword",
        "index": false
      },
      "age": {
        "type": "integer"
      },
      "desc": {
        "type": "text",
        "analyzer": "ik_smart",
        "copy_to": "full_name"
      }
    }
  }
}

name欄位不能夠用來搜索

null_value

  • 當欄位遇到null值時的處理策略,默認為null,即空值,此時ES會忽略該值,不會創建索引,可以通過設定該值得一個空值的替換值來對空值進行索引,可以用替換值進行對空值的搜索
PUT woniu48
{
  "mappings": {
    "properties": {
      "name": {
        "type": "keyword"
      },
      "age": {
        "type": "integer"
      },
      "desc": {
        "type": "text",
        "analyzer": "ik_smart"
      },
      "sex": {
        "type": "keyword",
        "null_value": "null"
      }
    }
  }
}

使用null替換了空值,下面添加一個空值

PUT woniu48/_doc/1
{
  "name": "zs",
  "age": 23,
  "desc": "中國人很好",
  "sex": null
}

可以使用替換的null值來進行空值搜索

GET woniu48/_search
{
  "query": {
    "match": {
      "sex": "null"
    }
  }
}

ignore_above

  • 該屬性是keyword型別的一個屬性,用來規定欄位值長度,超出這個長度的欄位將不會被索引,但是會存盤,
PUT woniu48
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "fields": {
          "pinyin": {
            "type": "keyword",
            "ignore_above": 5 
          }
        }
      },
      "age": {
        "type": "integer"
      }
    }
  }
}

多欄位特性 multi-fields

  • 允許對同一個欄位采用不同的配置,比如分詞,常見的例子如一個欄位我需要通過索引分詞查詢也需要能夠通過精裝匹配查詢
PUT woniu48
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "fields": {
          "pinyin": {
            "type": "keyword"
          }
        }
      },
      "age": {
        "type": "integer"
      }
    }
  }
}

index_options

  • 用來控制倒排索引記錄的內容

docs: 只記錄doc id
freqs : 記錄doc id和term frequencies
positions: 記錄doc id、term frequencies和term position
offsets: 記錄doc id、term frequencies、term position和character offsets
text型別默認配置為positions,其他默認為docs,記錄內容越多,占用空間越大

5.2 資料型別

核心資料型別
字串型: text、keyword
數值型: long、integer、short、byte、double、float、half_float、scaled_float
日期型別: date
布爾型別: boolean
二進制型別: binary
范圍型別: integer_range、float_range、long_range、double_range、date_range
復雜資料型別
陣列型別: array
物件型別: object
嵌套型別: nested object
地理位置資料型別
geo_point
geo_shape
專用型別
ip: 記錄IP地址
completion: 實作自動補全
token_count: 記錄分詞數
murmur3: 記錄字串hash值

5.3 Dynamic Mapping(自動映射)

ES在沒有配置Mapping的情況下新增檔案,ES可以自動識別檔案欄位型別,并動態生成欄位和型別的映射關系,

ES是依靠JSON檔案的欄位型別來實作自動識別欄位型別,支持的型別如下:

JSON型別 ES型別
null 忽略
boolean boolean
浮點型別 float
整數 long
object object
array 由第一個非null值得型別決定
string 匹配為日期格式則設為date型別(默認開啟);
匹配為數字的話設為float或long型別(默認關閉)設為text型別,并附帶keyword子欄位

6 DSL查詢

由ES提供豐富且靈活的查詢語言叫做DSL查詢(Query DSL),將查詢陳述句通過http request body發送到ES,主要包含如下引數:

query符合Query DSL語法的查詢陳述句
from、size
timeout
sort
,,,
例如:

GET woniu48/_search
{
"query": {
"term": {
"name": "lisi"
}
}
}

基于JSON定義的查詢語言,主要包含如下兩種型別

欄位類查詢

如term、match、range等,只針對某一個欄位進行查詢

復合查詢

如bool查詢等,包含一個或多個欄位類查詢或則復合查詢陳述句

6.1 欄位類查詢

Match Query流程

欄位類查詢主要包括以下兩類:

全文匹配
針對text型別的欄位進行全文檢索,會對查詢陳述句先進行分詞處理,如match、match_phrase等query型別
單詞匹配
不會對查詢陳述句做分詞處理,直接匹配欄位的倒排索引,如term、terms、range等query型別
全文匹配(Match Query)

GET woniu48/_search
{
  "query": {
    "match": {
      "username": "alfred way"
    }
  }
}


**通過operator引數可以控制單詞間的匹配關系,可選項為or或則and**

GET woniu48/_search
{
  "query": {
    "match": {
      "desc": {
        "query": "非常漂亮",
        "operator": "and"
      }
    }
  }
}

上面查詢如果分詞器分詞為“非常”、“漂亮”兩個詞,查詢匹配結果就必須同時包含這兩個詞的檔案

單詞匹配(Term Query)

GET woniu48/_search
{
  "query": {
    "term": {
      "name": "lisi"
    }
  }
}

一次傳入多個單詞進行查詢

GET woniu48/_search
{
  "query": {
    "terms": {
      "name": [
        "lisi",
        "wangmazi"
      ]
    }
  }
}

Range Query(范圍查詢)

GET woniu48/_search
{
  "query": {
    "range": {
      "age": {
        "gte": 20,
        "lte": 23
      }
    }
  }
}

6.2 復合查詢

復合查詢是指包含欄位類查詢或復合查詢的型別,主要包括以下幾類:

constant_score query
bool query *
dis_max query
function_score query
boosting query
Bool Query

布爾查詢由一個或多個布爾子句組成,主要包含如下4個:

Name Description
filter 只過濾符合條件的檔案,不計算相關性得分
must 檔案必須復合must中的所有條件,會影響相關性得分
must_not 檔案必須不符合must_not中的所有條件
should 檔案可以符合should中的條件,會影響相關性得分
Filter Filter查詢只過濾符合條件的檔案,不會進行相關性算分

ES針對Filter會有智能快取,因此其執行效率很高
做簡單匹配查詢且不考慮算分時,推薦使用filter替代query等

GET woniu48/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "name": "admin"
          }
        },
        {
          "range": {
            "age": {
              "gte": 25
            }
          }
        }
      ]
    }
  }
}
  • must
GET woniu48/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "desc": "漂亮的人"
          }
        },
        {
          "range": {
            "age": {
              "gte": 22
            }
          }
        }
      ]
    }
  }
}
  • must_not

查詢描述里面經過分詞有“漂亮”一詞以及不帶“非常”一詞的結果

GET woniu48/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "desc": "漂亮的人"
          }
        }
      ],
      "must_not": [
        {
          "match": {
            "desc": "非常好"
          }
        }
      ]
    }
  }
}
  • should

只包含should時,檔案必須至少滿足一個條件(minimun_should_match可以控制滿足條件的個數或則百分比)

例如:下面至少滿足一個條件

GET woniu48/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "desc": "漂亮的人"
          }
        },
        {
          "range": {
            "age": {
              "lte": 20
            }
          }
        }
      ]
    }
  }
}

例如:下面需要滿足兩個條件

GET woniu48/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "desc": "漂亮的人"
          }
        },
        {
          "range": {
            "age": {
              "lte": 20
            }
          }
        }
      ],
      "minimum_should_match": 2
    }
  }
}

同時包含should和must時,檔案不必滿足should中的條件,但是如果滿足條件,會增加相關性得分

該查詢只會以must匹配來搜索

GET woniu48/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "range": {
            "age": {
              "lte": 19
            }
          }
        }
      ],
      "must": [
        {
          "match": {
            "desc": "漂亮的人"
          }
        }
      ]
    }
  }
}

綜合實體

查詢年齡大于20并且包含“漂亮的人”描述或則年齡小于18的學員,分頁顯示第2頁,每頁顯示2條,且按照年齡由低到高排序

GET woniu48/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "must": [
              {
                "match": {
                  "desc": "漂亮的人"
                }
              },
              {
                "range": {
                  "age": {
                    "gte": 20
                  }
                }
              }
            ]
          }
        },
        {
          "range": {
            "age": {
              "lte": 18
            }
          }
        }
      ]
    }
  },
  "from": 2,
  "size": 2,
  "sort": [
    {
      "age": {
        "order": "desc"
      }
    }
  ]
}

7 SpringBoot集成

可以通過Spring Data Elasticsearch來進行操作,boot對其進行了集成:

導包

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

配置連接

spring:
  elasticsearch:
    rest:
      uris:
      - http://localhost:9200

注入模板物件

@Autowired
ElasticsearchOperations operations;

7.1 物件映射

ES的檔案對應于Java的物件,可以通過Spring-Data-Es提供的注解來進行關聯:

@Data
@Document(indexName = "woniu48")
public class Student {
	
	@Id
	@Field(type = FieldType.Integer,name = "id")
	private Integer id;
	
	@Field(type = FieldType.Keyword,name="name")
	private String name;
	
	@Field(type = FieldType.Integer,name="age")
	private Integer age;
	
	@Field(type = FieldType.Text,analyzer = "ik_max_word",name = "desc")
	private String desc;

}

@Document: 在類級別應用,以指示該類是映射到ES的哪一個Index,最重要的屬性是:
indexName: 用于存盤此物體的索引的名稱
@Id: 用來標識ID
@Field: 在欄位級別應用并定義欄位的屬性:
name: 欄位名稱
type: 欄位型別
analyzer: 分詞器

7.2 操作

保存(新增與更新)物件:

Student stu = new Student();
stu.setId(3333);
stu.setName("張三豐");
stu.setDesc("此人漲得不好看");
stu.setAge(100);
operations.save(stu);

洗掉物件:

//第一個引數是id
operations.delete("3333", Student.class);

查詢物件:

查詢有三種主要方式:

通過CriteriaQuery條件來查詢,可以簡單組合條件,不能分詞,適用于非常簡單的查詢

//查詢年齡在20-25之間或則名稱是"admin"的學員
Criteria c = new Criteria("age").between(20, 25)
	.or("name").is("admin");			
CriteriaQuery cq = new CriteriaQuery(c);
SearchHits<Student> shs = operations.search(cq, Student.class);
System.out.println(shs.getTotalHits());
shs.getSearchHits().forEach(student -> {
	System.out.println(student.getContent().getName()+":"+student.getContent().getAge());
});

通過StringQuery來查詢,直接在java這邊構建查詢json字串,不推薦使用

通過NativeSearchQuery來構建復雜查詢,包括bool查詢等等,推薦使用

/*查詢匹配非常漂亮的人或則年齡在90以上的*/

//構建NativeSearchQuery建造器
NativeSearchQueryBuilder nsqb = new NativeSearchQueryBuilder();
//構造Bool查詢條件		
BoolQueryBuilder bqb = new BoolQueryBuilder();
//通過該Bool查詢器構建should查詢器
List<QueryBuilder> should = bqb.should();
//向should里面添加兩個查詢條件
should.add(new MatchQueryBuilder("desc", "非常漂亮的人"));
should.add(new RangeQueryBuilder("age").gt(90));
//注冊bool查詢條件
nsqb.withQuery(bqb);
//注冊分頁(第一頁,顯示3條)
nsqb.withPageable(PageRequest.of(0, 3));
//注冊排序(age降序)
nsqb.withSort(SortBuilders.fieldSort("age").order(SortOrder.DESC));
//構建NativeSearchQuery
NativeSearchQuery nsq = nsqb.build();
//執行查詢方法		
SearchHits<Student> shs = operations.search(nsq, Student.class);
System.out.println(shs.getTotalHits());
shs.getSearchHits().forEach(x -> {
	Student stu = x.getContent();
	System.out.println(stu.getName()+":"+stu.getDesc()+":"+stu.getAge());
});

查詢結果高亮顯示

//創建高亮顯示幕
HighlightBuilder hb = new HighlightBuilder();
//設定高亮欄位
hb.field("desc");
//設定為false,匹配欄位都會高亮顯示
hb.requireFieldMatch(false);
//設定如何高亮顯示
hb.preTags("<span style=\"color:red\">");
hb.postTags("</span>");
//設定高亮顯示范圍以字符為單位
hb.fragmentSize(800);
//設定高亮顯示的開始位置
hb.numOfFragments(0);
		
NativeSearchQueryBuilder nsqb = new NativeSearchQueryBuilder();
//注冊高亮顯示幕
nsqb.withHighlightBuilder(hb);
nsqb.withQuery(new MatchQueryBuilder("desc", "非常漂亮"));
NativeSearchQuery nsq = nsqb.build();
SearchHits<Student> shs = operations.search(nsq, Student.class);
shs.getSearchHits().forEach(x -> {
	Student stu = x.getContent();
    String desc = stu.getDesc();
    //獲取高亮顯示欄位
	List<String> hs = x.getHighlightField("desc"); 
	if(hs != null && hs.size() > 0) desc = hs.get(0);
	System.out.println(stu.getName()+":"+desc);
});

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/258874.html

標籤:其他

上一篇:30行代碼實作朋友圈自動點贊

下一篇:設計模式(二十二)——狀態模式(APP抽獎活動+借貸平臺原始碼剖析)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more