各位小伙伴們,今天是今年的最后一天,這是我今年的最后一篇博客,在這里祝大家新年快樂!本次講的是近幾年比較流行的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”: “wb@bbcc.com”,
“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,

這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 中文分詞器
中文分詞器是將一個漢字序列切分成一個一個單獨的詞,在英語中,單詞之間是以空格作為自然分界符,漢語中詞沒有一個形式上的分界符,背景關系不同,分詞結果迥異,比如交叉歧義問題,比如下面兩種分詞都合理:
- 乒乓球拍/賣/完了
- 乒乓球/拍賣/完了
常用分詞系統
-
IK
-
實作中英文單詞的切分,支持ik_smart、ik_maxword等模式,
-
可自定義詞庫,支持熱更新分詞詞典
-
https://github.com/medcl/elasticsearch-analysis-ik
-
-
jieba
- python中最流行的分詞系統,支持分詞和詞性標注
- 支持繁體分詞、自定義詞典、并行分詞等
- https://github.com/sing1ee/elasticsearch-jieba-plugin
IK的使用
-
安裝
- git clone https://github.com/medcl/elasticsearch-analysis-ik
- cd elasticsearch-analysis-ik
- mvn clean
- mvn compile
- mvn package
- 拷貝和解壓release下的檔案: #{project_path}/elasticsearch-analysis-ik/target/releases/elasticsearch-analysis-ik-*.zip 到你的 elasticsearch 插件目錄, 如: plugins/ik 重啟elasticsearch
-
測驗
POST _analyze { "analyzer": "ik_smart", "text": "中華人民共和國國歌" }POST _analyze { "analyzer": "ik_max_word", "text": "中華人民共和國國歌" } -
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 欄位類查詢
欄位類查詢主要包括以下兩類:
- 全文匹配
- 針對text型別的欄位進行全文檢索,會對查詢陳述句先進行分詞處理,如match、match_phrase等query型別
- 單詞匹配
- 不會對查詢陳述句做分詞處理,直接匹配欄位的倒排索引,如term、terms、range等query型別
全文匹配(Match Query)
GET woniu48/_search
{
"query": {
"match": {
"username": "alfred way"
}
}
}
Match Query流程

通過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/qita/258916.html
標籤:其他
