elasticsearch 高级搜索示例 es7.0
1 基礎(chǔ)數(shù)據(jù)
1.1 創(chuàng)建索引
PUT mytest
{
"mappings": {
"properties": {
"title": {
"type": "text",
"fields": {
"keyword": {
"type": "text",
"analyzer": "standard"
}
}
},
"tag": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"content": {
"type": "text",
"fields": {
"std": {
"type": "text",
"analyzer": "standard"
},
"cn": {
"type": "text",
"analyzer": "ik_smart"
}
}
},
"score": {
"type": "byte"
},
"time":{
"type": "date"
}
}
},
"settings": {
"index": {
"number_of_shards": "1",
"number_of_replicas": "0"
}
}
}
1.2 寫入數(shù)據(jù)
POST mytest/_doc/001
{
"title": "好評不錯",
"tag": "精彩",
"content": "這里必須有一些內(nèi)容,來表示這個評論是好評",
"score": 90,
"time": 1596441469000
}
POST mytest/_doc/002
{
"title": "一般評價",
"tag": "普通",
"content": "這里可以有一些內(nèi)容,來表示這個評論是一般的",
"score": 80,
"time": 1596355069000
}
POST mytest/_doc/003
{
"title": "很差的評價",
"tag": "TCL",
"content": "這里沒有一些內(nèi)容,來表示這個評論是OK的",
"score": 20,
"time": 1596268669000
}
POST mytest/_doc/004
{
"title": "超級好評",
"tag": "精彩",
"content": "這里必須有一些內(nèi)容,來表示這個評論是好評好評好評好評好評好評好評好評好評好評好評好評好評",
"score": 2,
"time": 1596441469000
}
2 短語匹配
2.1 不指定匹配的 fields 時候, 是否會查找全部字段?
不指定 fields 搜索
POST mytest/_search
{
"explain": true,
"query": {
"match": {
"content": "好評"
}
}
}
搜索結(jié)果為 3 條。在 explain 的結(jié)果中可以看到, details 評分統(tǒng)計了兩個字段的結(jié)果
為了驗證上面結(jié)果, 在指定域搜索只能看到一條結(jié)果
POST mytest/_search
{
"query": {
"match": {
"content.cn": "好評"
}
}
}
2.2 match 和 match_phrase 區(qū)別
POST mytest/_search
{
"explain": false,
"query": {
"match": {
"content.cn":{
"query": "這里可以有一些內(nèi)容",
"analyzer": "ik_smart"
}
}
}
}
"這里可以有一些內(nèi)容" 通過 ik_smart 分詞器被分成了 [這里 可以 有 一些 內(nèi)容]
五個詞都放入到 es 中搜索, 所以這里可以搜索出三個結(jié)果
可以通過比例限制匹配的結(jié)果, 限制到 90% 后, 只能匹配到 1 條結(jié)果
POST mytest/_search
{
"query": {
"match": {
"content.cn":{
"query": "這里可以有一些內(nèi)容",
"analyzer": "ik_smart",
"minimum_should_match": "90%"
}
}
}
}
match_phrase 只能匹配到 1 條結(jié)果, 如果把文本換成 "這里可以有內(nèi)容一些", 就不能匹配到內(nèi)容了
這時需要使用 slop 完成近似匹配, 允許有順序的差異. 同時, 使用 match 匹配的時候, 詞的順序不影響結(jié)果得分
POST mytest/_search
{
"query": {
"match_phrase": {
"content.cn":{
"query": "這里可以有一些內(nèi)容",
"analyzer": "ik_smart",
"slop": 0
}
}
}
}
2.3 精確搜索的時候, 可以使用默認(rèn)分詞器, 以達(dá)到精確的目的
在搜索中輸入 "以有一些內(nèi)容" 不完整的內(nèi)容, 也可以搜索到精確的結(jié)果
修改為 match 可以
POST mytest/_search
{
"query": {
"match_phrase": {
"content.std":{
"query": "以有一些內(nèi)容",
"analyzer": "standard"
}
}
}
}
3 自定義打分
3.1 打分公式
score(q,d) = queryNorm(q) //歸一化因子
·coord(q,d) //協(xié)調(diào)因子
·∑( tf(t in d) //詞頻
·idf(t)2 //逆向文檔頻率
·t.getBoost() //權(quán)重
·norm(t,d) //字段長度歸一值
)(t in q)
queryNorm 查詢歸化因子: 會被應(yīng)用到每個文檔, 不能被更改, 總而言之, 可以被忽略
coord 協(xié)調(diào)因子: 可以為那些查詢詞包含度高的文檔提供獎勵, 文檔里出現(xiàn)的查詢詞越多, 它越有機(jī)會成為好的匹配結(jié)果
協(xié)調(diào)因子將評分與文檔里匹配詞的數(shù)量相乘,然后除以查詢里所有詞的數(shù)量,如果使用協(xié)調(diào)因子,評分會變成:
文檔里有 fox → 評分: 1.5 * 1 / 3 = 0.5
文檔里有 quick fox → 評分: 3.0 * 2 / 3 = 2.0
文檔里有 quick brown fox → 評分: 4.5 * 3 / 3 = 4.5
協(xié)調(diào)因子能使包含所有三個詞的文檔比只包含兩個詞的文檔評分要高出很多
3.2 提升查詢權(quán)重
POST mytest/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"title": {"query": "好評", "boost": 10}
}
},
{"match": {"content": "有一些內(nèi)容"}
}
]
}
}
}
3.3 結(jié)合 function_score 查詢 與 field_value_factor 查詢可以實(shí)現(xiàn)按照文檔的字段來影響文檔評分
POST mytest/_search
{
"query": {
"function_score": {
"query": {
"multi_match": {"query": "好評","fields": ["title", "content"]}
},
"functions": [
{"field_value_factor": {"field": "score"}}
]
}
}
}
new_score = old_score * number_of_votes
這樣會導(dǎo)致 votes 為 0 的文檔評分為 0,而且 votes 值過大會掩蓋掉全文評分
3.4 一般會使用 modifier 參數(shù)來平滑 votes 的值
POST mytest/_search
{
"query": {
"function_score": {
"query": {
"multi_match": {"query": "好評","fields": ["title", "content"]}
},
"functions": [
{"field_value_factor": {"field": "score", "modifier": "log1p"}}
]
}
}
}
應(yīng)用值為 log1p 的 modifier 后的評分計算公式:
new_score = old_score * log(1 + number_of_votes)
modifier 的可以為: none ,log ,log1p ,log2p ,ln ,ln1p ,ln2p ,square ,sqrt ,reciprocal
3.5 factor 可以通過將 votes 字段與 factor 的積來調(diào)節(jié)受歡迎程度效果的高低
"functions": [
{"field_value_factor": {"field": "score", "modifier": "ln1p", "factor": 10}}
]
添加了 factor 會使公式變成這樣:
new_score = old_score * log(1 + factor * number_of_votes)
3.6 通過參數(shù) boost_mode 來控制函數(shù)與查詢評分 _score 合并后的結(jié)果,參數(shù)接受的值
multiply: 評分 _score 與函數(shù)值的積(默認(rèn))
sum: 評分 _score 與函數(shù)值的和
min: 評分 _score 與函數(shù)值間的較小值
max: 評分 _score 與函數(shù)值間的較大值
replace: 函數(shù)值替代評分 _score
"functions":[],
"boost_mode": "sum"
之前請求的公式現(xiàn)在變成下面這樣:
new_score = old_score + log(1 + 0.1 * number_of_votes)
3.7 可以使用 max_boost 參數(shù)限制一個函數(shù)的最大效果
"boost_mode": "sum"
"max_boost": 1.5
無論 field_value_factor 函數(shù)的結(jié)果如何,最終結(jié)果都不會大于 1.5 。
注意 max_boost 只對函數(shù)的結(jié)果進(jìn)行限制,不會對最終評分 _score 產(chǎn)生直接影響。
3.8 評分模式 score_mode
每個函數(shù)返回一個結(jié)果,所以需要一種將多個結(jié)果縮減到單個值的方式,然后才能將其與原始評分 _score 合并。
評分模式 score_mode 參數(shù)正好扮演這樣的角色, 它接受以下值:
multiply : 函數(shù)結(jié)果求積(默認(rèn))。
sum : 函數(shù)結(jié)果求和。
avg : 函數(shù)結(jié)果的平均值。
max : 函數(shù)結(jié)果的最大值。
min : 函數(shù)結(jié)果的最小值。
first : 使用首個函數(shù)(可以有過濾器,也可能沒有)的結(jié)果作為最終結(jié)果
在本例中,我們將每個過濾器匹配結(jié)果的權(quán)重 weight 求和,并將其作為最終評分結(jié)果,所以會使用 sum 評分模式。
不與任何過濾器匹配的文檔會保有其原始評分, _score 值的為 1 。
3.9 衰減函數(shù)
這需要使用 function_score 查詢提供的一組 衰減函數(shù)(decay functions)
linear 線性函數(shù)
exp 指數(shù)函數(shù)
gauss 高斯函數(shù)
所有三個函數(shù)都接受如下參數(shù):
origin:中心點(diǎn) 或字段可能的最佳值,落在原點(diǎn) origin 上的文檔評分 _score 為滿分 1.0 。
scale:衰減率,即一個文檔從原點(diǎn) origin 下落時,評分 _score 改變的速度。(例如,每 £10 歐元或每 100 米)。
decay:從原點(diǎn) origin 衰減到 scale 所得的評分 _score ,默認(rèn)值為 0.5 。
offset:以原點(diǎn) origin 為中心點(diǎn),為其設(shè)置一個非零的偏移量 offset 覆蓋一個范圍,而不只是單個原點(diǎn)。在范圍 -offset <= origin <= +offset 內(nèi)的所有評分 _score 都是 1.0
"functions": [
{
"exp": {
"time": {
"origin": "1596530751000",
"scale": "10d",
"offset": "5d",
"decay": 0.5
}
}
}
]
總結(jié)
以上是生活随笔為你收集整理的elasticsearch 高级搜索示例 es7.0的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 路由器怎么限制手机WIFI速度路由器如何
- 下一篇: 第十一节:Bundles压缩合并js和c