ElasticSearch (ES)學習之路(五)ES 複雜搜索( 匹配 過濾 精準 排序 高亮)
在上文中,我們查詢小紅 其kinbana 語法是這樣寫的
GET /lei/one/_search?q=name:小麗
前文中,也是做了分析,由於有多個包含‘小麗’的數據,所以我們在搜索’小麗’ 時將與之相匹配的數據全部搜索了出來,並且 ,搜索出的每條數據都包含了一個_score 分值字段
其實質意義:_score=分值=匹配度 結果匹配度越高 分值則越高,則排名越是考前
在實際查詢語法時候,我們大多不會寫q=xxxxx ,而是寫查詢參數體 類似於 添加數據時的請求體,其查詢語法如下
GET /索引名/類型名/_search
{
"query":{
"查詢參數體 查詢條件"
}
}
例如,我們還是接着 查詢小麗的例子進行編寫
單條件查詢
使用kinbanna的好處,語法可以提示 如下 field 列名 match 匹配
GET /lei/one/_search
{
"query": {
"match": {
"name": "小麗"
}
}
}
此操作就對應着我們開始編寫的一行 語句 GET /lei/one/_search?q=name:小麗 ,只是更具有層次性,可讀性更好,看,查詢結果也是一模一樣的。 這裏匹配是什麼意思呢 就是隻要包含小麗的就算匹配 小麗 小麗2 都會命中
這個hits 就是查詢出的結果集對象,其中即包含了文檔數以及索引信息概括,以及包含了每個具體的文檔數據
查詢結果字段過濾
何爲結果字段過濾呢?我們在寫sql語句的時候,可以select * ,也可以select 列1,列2 , 根據我們select 的不同,返回不同的字段信息
那麼在es 中也是有這個功能的
例如,在上方查詢結果的,我們發現文檔中的 三個字段 name age birthday 都被查詢出來了
本文當前呢,爲了演示,字段則返回 name age
GET /lei/one/_search
{
"query": {
"match": {
"name": "小麗"
}
}
, "_source": ["name","age"]
}
分頁
爲什麼要分頁,,,我這裏就不用細說了吧(都學到es了,還不懂爲啥要分頁,那切雀雀吧)
由於我這裏只有兩條數據哈,所以分頁呢,暫時一頁一條即可
GET /lei/one/_search
{
"query": {
"match": {
"name": "小麗"
}
}
, "_source": ["name","age"]
,"from": 0
, "size": 1
}
from =(當前頁-1)*每頁長度
size= 每頁長度(即每頁要展示的長度)
注意的是.from size 都是與query爲同級
排序
由於我之前添加文檔一個採用了put指定_id,一個採用post 隨機生成_ _ id ,我這裏故採用年齡進行排序吧
排序,只需要在與 query同級別下 輸入"sort" 其Kinbanba 就會自動幫我們補全 排序語法
GET /lei/one/_search
{
"query": {
"match": {
"name": "小麗"
}
},
"sort": [
{
"age": {
"order": "desc"
}
}
]
}
多條件匹配查詢
等價於 sql 中 where xxx =?? and xxx=?? 查詢名字爲小麗 並且年齡爲22歲
and
must 必須的意思 等價於 and 條件
GET /lei/one/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "小麗"
}
},
{
"match": {
"age": "22"
}
}
]
}
}
}
or
等價於 sql 中 where xxx =?? or xxx=?? 查詢名字爲小麗 或者年齡爲222歲
or 條件 很簡單 將上方的 must 改爲 should (應該 )
should 應該的意思 等價於or 條件 拼接
GET /lei/one/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"name": "小麗"
}
},
{
"match": {
"age": "222"
}
}
]
}
}
}
新增字段
查詢某列中的值 包含xxx的數據 可以是數組中某一元素值等等 (我先前準備的數據沒有哈,所以這裏添加一個列,並添加一些數據)
POST /lei/one
{
"properties": {
"hobby": {
"type": "array"
}
}
}
POST /lei/one/2/_update
{
"doc":{
"hobby":["籃球","擊劍"]
}
}
POST /lei/one/7ErnHHMBjoLvVc_LTjx_/_update
{
"doc":{
"hobby":["足球","爬山"]
}
}
查詢某列中 包含XXX 的文檔信息
查詢某列中 包含某些值得文檔 查詢時 “列名”:" 包含的值 多個用空格隔開"
等價於 mysql 中 where xxx like “xxx”
我們可以看到 匹配度越高 其分值越高 排名也是靠前
!= 條件查詢
不等於 等價於msql中的 where xxx!= ??
我這裏查詢年齡不爲222歲
GET /lei/one/_search
{
"query": {
"bool": {
"must_not": [
{
"match": {
"age": "222"
}
}
]
}
}
}
條件過濾
此方法與 where and 語法類似 但是 不同的是 其可以做大小於等一些邏輯判斷 must 的話,僅僅只表示=匹配
語法解釋 : 查詢匹配名爲小麗 並且 年齡大於等於30 where name=‘小麗’ and age >=30
GET /lei/one/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "小麗"
}
}
],
"filter": {
"range": {
"age": {
"gte": 30
}
}
}
}
}
}
還可以區間過濾 ,例如 查詢名字爲小麗 且年齡在22-30之間
精確查詢
trem 精確查詢 與match匹配不同 只會查詢其精確到具體的條件
新建索引庫 並插入數據
PUT /tremdb
{
"mappings": {
"properties": {
"name":{
"type": "keyword"
},
"desc":{
"type": "text"
}
}
}
}
PUT /tremdb/_doc/1
{
"name":"曹操魏武帝",
"desc":"魏武帝,愛人妻,三國"
}
PUT /tremdb/_doc/2
{
"name":"劉備漢昭烈帝",
"desc":"漢昭烈帝,人稱大耳賊,三國"
}
PUT /tremdb/_doc/3
{
"name":"孫權吳大帝",
"desc":"吳大帝,江東小霸王之弟,三國"
}
我們先前也講過 keyword 是不會被分詞的 那麼我們這裏可以測試一下
我們以名字作爲精確搜索,“帝” 沒有結果
以武帝 作爲精確搜索條件----還是未命中
以曹操魏武 爲精確搜索條件 ----還是未命中
以曹操魏武帝 爲精確搜索條件 ----命中
可以得出結論 字段類型爲keyword 的時候 ,其不會被分詞器進行解析 只有以完整的值進行查詢纔會被命中
測試desc text 類型 text 會被分詞 包含 帝 所以我們以帝 進行查詢 則能獲取到結果
精確查詢多個
高亮顯示
高亮,在搜索網站時 很常見 ,例如,我們的京東 /百度
搜一波 外星人 可以看到 外星人關鍵字 全部高亮顯示了,那麼是怎麼做到的呢??
高亮!
可以看到 我搜索的小麗 結果 都添加了一個高亮字段 並用 標籤包裹起來了,這就是高亮!
可能有人想問,高亮 爲什麼呢 ?別人都是紅色的 ,我也想要!
可以,這個需求可以做的!
自定義高亮顏色
es 高亮 是支持我們自定義顏色的! 如何自定義呢 注意兩個json 字段的使用!
"pre_tags": "<font color=red>", 前綴
"post_tags": "</font>", 後綴
設置這兩個標籤後呢,其搜索的高亮 將會被前後綴包裹
完整查詢語句:
注意,我這裏定義了 標籤,爲了在 typora 以及csdn 上直接顯示
GET /lei/one/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "小麗"
}
}
]
}
},
"highlight": {
"pre_tags": "<font color=red>",
"post_tags": "</font>",
"fields": {
"name":{}
}
}
}
小麗
基本的ES 語法差不多就到這裏了! 後續隨着學習的深度不斷添加 !!!