elasticsearch多欄位搜尋
阿新 • • 發佈:2019-01-08
多欄位搜尋
多字串查詢
- boost 引數 “最佳” 值,較為簡單的方式就是不斷試錯,比較合理的區間處於 1 到 10 之間,當然也有可能是 15 。如果為 boost 指定比這更高的值,將不會對最終的評分結果產生更大影響,因為評分是被 歸一化的
GET /_search
{
"query": {
"bool": {
"should": [
{ "match": {
"title": {
"query": "War and Peace",
"boost": 2
}}},
{ "match" : {
"author": {
"query": "Leo Tolstoy",
"boost": 2
}}},
{ "bool": { # 不寫在上面一層,是因為tarnslator理論是隻佔總評分的三分之一,在上面一層就是四分之一了
"should": [
{ "match": { "translator": "Constance Garnett" }},
{ "match" : { "translator": "Louise Maude" }}
]
}}
]
}
}
}
最佳欄位
- dis_max(Disjunction Max Query)查詢,意思是 或,指的是: 將任何與任一查詢匹配的文件作為結果返回,但只將最佳匹配的評分作為查詢的評分結果返回;為了理解這句話,做給小實驗
- 建立測試資料
DELETE my_index
PUT /my_index/my_type/1
{
"title": "Quick brown fox rabbits",
"body": "Brown eats rabbits are commonly seen."
}
PUT /my_index/my_type/2
{
"title": "Keeping pets healthy",
"body": "My quick brown fox eats rabbits on a regular basis."
}
- 查詢比較
GET /my_index/my_type/_search
{
"query": {
"bool": {
"should": [
{ "match": { "title": "Brown fox eats" }},
{ "match": { "body": "Brown fox eats" }}
]
}
}
}
結果:id為1的文件在前面
GET /my_index/my_type/_search
{
"query": {
"dis_max": { # dis_max查詢,文件查詢的某個match評分最高的作為結果返回
"queries": [
{ "match": { "title": "Brown fox eats" }},
{ "match": { "body": "Brown fox eats" }}
]
}
}
}
結果:
最佳欄位查詢調優
tie_breaker:一個簡單的 dis_max 查詢會採用單個最佳匹配欄位, 而忽略其他的匹配,指定 tie_breaker 這個引數可以將其他匹配語句的評分也考慮其中;比如:
- 簡單dis_max查詢
{ "query": { "dis_max": { "queries": [ { "match": { "title": "Quick pets" }}, { "match": { "body": "Quick pets" }} ] } } }
結果:
- tie_breaker
GET /my_index/my_type/_search { "query": { "dis_max": { "queries": [ { "match": { "title": "Quick pets" } }, { "match": { "body": "Quick pets" } } ], "tie_breaker": 0.3 } } }
結果:
- 簡單dis_max查詢
tie_breaker 引數提供了一種 dis_max 和 bool 之間的折中選擇,範圍
[0,1]
範圍建議0.1-0.4, 0 代表使用 dis_max 最佳匹配語句的普通邏輯, 1 表示所有匹配語句同等重要,步驟如下:- 獲得最佳匹配語句的評分 _score
- 將其他匹配語句的評分結果與 tie_breaker 相乘
- 對以上評分求和並規範化
multi_match查詢
- 為能在多個欄位上反覆執行相同查詢提供了一種便捷方式,multi_match 多匹配查詢的型別有多種,其中的三種恰巧與 瞭解我們的資料 中介紹的三個場景對應,即: best_fields 、 most_fields 和 cross_fields (最佳欄位、多數字段、跨欄位),預設情況下,查詢的型別是 best_fields , 這表示它會為每個欄位生成一個 match 查詢,然後將它們組合到 dis_max 查詢的內部
GET /my_index/my_type/_search
{
"query": {
"dis_max": {
"queries": [
{
"match": {
"title": {
"query": "Quick brown fox",
"minimum_should_match": "30%"
}
}
},
{
"match": {
"body": {
"query": "Quick brown fox",
"minimum_should_match": "30%"
}
}
}
],
"tie_breaker": 0.3
}
}
}
查詢等價於
GET /my_index/my_type/_search
{
"query": {
"multi_match": {
"query": "Quick brown fox",
"type": "best_fields", # 預設為best_fields可以不指定
"fields": [
"title",
"body"
],
"tie_breaker": 0.3,
"minimum_should_match": "30%" # 這樣的引數會被傳遞到生成的 match 查詢中
}
}
}
結果:
查詢欄位名稱的模糊匹配
- 欄位名稱可以用模糊匹配的方式給出
{
"multi_match": {
"query": "Quick brown fox",
"fields": "*_title"
}
}
提升單個欄位的權重
- 可以使用 ^ 字元語法為單個欄位提升權重,在欄位名稱的末尾新增 ^boost
{
"multi_match": {
"query": "Quick brown fox",
"fields": [ "*_title", "chapter_title^2" ]
}
}
多欄位對映
- 是對我們的欄位索引兩次, 一次使用詞幹模式以及一次非詞幹模式
- 新增多欄位對映
DELETE /my_index
PUT /my_index
{
"settings": { "number_of_shards": 1 },
"mappings": {
"my_type": {
"properties": {
"title": {
"type": "string",
"analyzer": "english",
"fields": {
"std": {
"type": "string",
"analyzer": "standard"
}
}
}
}
}
}
}
- Put值
PUT /my_index/my_type/1
{ "title": "My rabbit jumps" }
PUT /my_index/my_type/2
{ "title": "Jumping jack rabbits" }
- get title
GET /my_index/_search
{
"query": {
"match": {
"title": "jumping rabbits"
}
}
}
# 結果命中2條
- get title.std
GET /my_index/_search
{
"query": {
"match": {
"title.std": "jumping rabbits"
}
}
}
# 結果命中1條
- most_fields 合併兩次索引的評分,加權重
GET /my_index/_search
{
"query": {
"multi_match": {
"query": "jumping rabbits",
"type": "most_fields",
"fields": [ "title^10", "title.std" ]
}
}
}
跨欄位實體搜尋
- 當多個屬性結合起來決定一個事物的時候,可以使用multi_match查詢(依次查詢每個欄位並將每個欄位的匹配評分結果相加),比如
以下欄位表示一個人資訊
{
"street": "5 Poland Street",
"city": "London",
"country": "United Kingdom",
"postcode": "W1V 3DG"
}
可以如下查詢
{
"query": {
"bool": {
"should": [
{ "match": { "street": "Poland Street W1V" }},
{ "match": { "city": "Poland Street W1V" }},
{ "match": { "country": "Poland Street W1V" }},
{ "match": { "postcode": "Poland Street W1V" }}
]
}
}
}
或
{
"query": {
"multi_match": {
"query": "Poland Street W1V",
"type": "most_fields", # 合併所有匹配欄位的評分
"fields": [ "street", "city", "country", "postcode" ]
}
}
}
- most_fields也存在些問題
- 是為多數字段匹配 任意 詞設計的,而不是在 所有欄位 中找到最匹配的
- 不能使用 operator 或 minimum_should_match 引數來降低次相關結果造成的長尾效應
- 詞頻對於每個欄位是不一樣的,而且它們之間的相互影響會導致不好的排序結果
自定義_all
- copy_to 引數來實現給欄位新增自定義_all欄位
PUT /my_index
{
"mappings": {
"person": {
"properties": {
"first_name": {
"type": "string",
"copy_to": "full_name"
},
"last_name": {
"type": "string",
"copy_to": "full_name"
},
"full_name": {
"type": "string"
}
}
}
}
}
可通過地址http://blog.csdn.net/jiao_fuyou/article/details/49800969
來更深入學習_all
cross-fields跨欄位查詢
自定義 _all 的方式是一個好的解決方案,只需在索引文件前為其設定好對映,然而還可以使用cross_fields 型別進行 multi_match 查詢
cross_fields 使用詞中心式(term-centric)的查詢方式,這與 best_fields 和 most_fields 使用欄位中心式(field-centric)的查詢方式非常不同
- 欄位中心式
GET /_validate/query?explain
{
"query": {
"multi_match": {
"query": "peter smith",
"type": "most_fields",
"operator": "and",
"fields": [ "first_name", "last_name" ]
}
}
}
對於匹配的文件, peter 和 smith 都必須同時出現在相同欄位中,要麼是 first_name 欄位,要麼 last_name 欄位
(+first_name:peter +first_name:smith)
(+last_name:peter +last_name:smith)
- 詞中心式,詞 peter 和 smith 都必須出現,但是可以出現在任意欄位中,cross_fields 型別首先分析查詢字串並生成一個詞列表,然後它從所有欄位中依次搜尋每個詞
GET /_validate/query?explain
{
"query": {
"multi_match": {
"query": "peter smith",
"type": "cross_fields",
"operator": "and",
"fields": [ "first_name", "last_name" ]
}
}
}
為了讓 cross_fields 查詢以最優方式工作,所有的欄位都須使用相同的分析器
- 採用 cross_fields 查詢與 自定義 _all 欄位 相比,其中一個優勢就是它可以在搜尋時為單個欄位提升權重
GET /books/_search
{
"query": {
"multi_match": {
"query": "peter smith",
"type": "cross_fields",
"fields": [ "title^2", "description" ]
}
}
}
- 需要在 multi_match 查詢中避免使用 not_analyzed 欄位