Elasticsearch 7.x 深入【4】DSL查詢(xún)【一】term級(jí)別的查詢(xún)

1. 借鑒

極客時(shí)間 阮一鳴老師的Elasticsearch核心技術(shù)與實(shí)戰(zhàn)
Elasticsearch搜索引擎第十篇-Query DSL詳解
如何使Elasticsearch的前綴查詢(xún)(prefix query)效果同sql的like 'prefix%'
官方文檔 term-level-queries
官方文檔 regexp語(yǔ)法
Elasticsearch:fuzzy 搜索 (模糊搜索)
盤(pán)點(diǎn)Elasticsearch中的查詢(xún)套路
官方文檔 rewrite

2. 開(kāi)始

基于term的查詢(xún)

    1. term級(jí)別的查詢(xún)有以下幾種:term/terms/terms set,range,exists,prefix,wildcard,regexp,fuzzy,ids。
    1. 對(duì)輸入不做分詞,這點(diǎn)要注意

接下來(lái),我們以下列數(shù)據(jù)為例,來(lái)介紹以下基于term的查詢(xún).

POST /product/_bulk
{"index": { "_id": 1 }}
{"produceId":"HKXL-1234-SKOX", "name": "測(cè)試產(chǎn)品1", "date": "2019-05-20", "price": 10}
{"index": { "_id": 2 }}
{"produceId":"UJSK-1234-BSUA", "name": "測(cè)試產(chǎn)品2", "price": 20, "date": "2020-04-15"}
{"index": { "_id": 3 }}
{"produceId":"HSYA-1234-MLBS", "name": "測(cè)試產(chǎn)品3", "price": 40, "date": "2020-01-20"}
{"index": { "_id": 4 }}
{"produceId":"HSYA-1234-MLBS", "name": "測(cè)試產(chǎn)品4", "price": 40, "date": "2020-01-20", "tag": ["機(jī)械"]}

term

GET /product/_search
{
  "query": {
    "term": {
      "name": {
        "value": "測(cè)試產(chǎn)品4"
      }
    }
  }
}
  • 查詢(xún)結(jié)果如下:
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}
  • 嗯,啥也沒(méi)有,是不是覺(jué)得很奇怪,不是不對(duì)輸入進(jìn)行分詞嗎?為啥查不到呢?我們前有說(shuō)過(guò)索引,對(duì)text類(lèi)型,es會(huì)進(jìn)行分詞,默認(rèn)使用standard分詞器進(jìn)行分詞,我們來(lái)看一下standard分詞器對(duì)”測(cè)試產(chǎn)品4“的分詞結(jié)果
GET /_analyze
{
  "text": "測(cè)試產(chǎn)品4",
  "analyzer": "standard"
}
  • 分詞結(jié)果
{
  "tokens" : [
    {
      "token" : "測(cè)",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "<IDEOGRAPHIC>",
      "position" : 0
    },
    {
      "token" : "試",
      "start_offset" : 1,
      "end_offset" : 2,
      "type" : "<IDEOGRAPHIC>",
      "position" : 1
    },
    {
      "token" : "產(chǎn)",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "<IDEOGRAPHIC>",
      "position" : 2
    },
    {
      "token" : "品",
      "start_offset" : 3,
      "end_offset" : 4,
      "type" : "<IDEOGRAPHIC>",
      "position" : 3
    },
    {
      "token" : "4",
      "start_offset" : 4,
      "end_offset" : 5,
      "type" : "<NUM>",
      "position" : 4
    }
  ]
}
  • 可以看到是每個(gè)字是單獨(dú)成詞,term對(duì)輸入不進(jìn)行分詞,索引沒(méi)有匹配上的關(guān)鍵字,自然也就沒(méi)有文檔被檢索出來(lái),那我們?cè)撊绾尾樵?xún)出來(lái)呢?可以使用keyword屬性進(jìn)行查詢(xún),但必須是精確的【啥意思?就是你要搜索”測(cè)試產(chǎn)品4“,必須是”測(cè)試產(chǎn)品4“這5個(gè)字符全部】
GET /product/_search
{
  "query": {
    "term": {
      "name.keyword": {
        "value": "測(cè)試產(chǎn)品4"
      }
    }
  }
}

terms

了解了term,我們來(lái)看下terms查詢(xún)。term是單值匹配,terms就是多值。

GET /product/_search
{
  "query": {
    "terms": {
      "name": [
        "好優(yōu)肯",
        "4"
      ]
    }
  }
}

terms set

  • 這里直接翻譯官網(wǎng)的話(huà)了,更容易理解
terms_set查詢(xún)與terms查詢(xún)相同,只是您可以定義返回文檔所需的匹配術(shù)語(yǔ)的數(shù)量。例如:
- 字段programming_languages包含一系列已知的編程語(yǔ)言,如c++、java或php,供求職者使用。您可以使用terms_set查詢(xún)來(lái)返回至少匹配這兩種語(yǔ)言的文檔。
- 一個(gè)名為permissions的字段包含應(yīng)用程序的可能用戶(hù)權(quán)限列表。您可以使用terms_set查詢(xún)來(lái)返回匹配這些權(quán)限子集的文檔。

在大多數(shù)情況下,需要在索引中包含一個(gè)數(shù)字字段映射來(lái)使用terms_set查詢(xún)。此數(shù)字字段包含返回文檔所需的匹配項(xiàng)的數(shù)目。

# 創(chuàng)建索引
PUT /job-candidates
{
    "mappings": {
        "properties": {
            "name": {
                "type": "keyword"
            },
            "programming_languages": {
                "type": "keyword"
            },
            "required_matches": {
                "type": "long"
            }
        }
    }
}

# 索引兩篇文檔
PUT /job-candidates/_doc/1?refresh
{
    "name": "Jane Smith",
    "programming_languages": ["c++", "java"],
    "required_matches": 2
}

PUT /job-candidates/_doc/2?refresh
{
    "name": "Jason Response",
    "programming_languages": ["java", "php"],
    "required_matches": 2
}
  • 可以使用required_matches字段值作為返回terms_set查詢(xún)中的文檔所需的匹配項(xiàng)數(shù)量。
GET /job-candidates/_search
{
    "query": {
        "terms_set": {
            "programming_languages": {
                "terms": ["c++", "java", "php"],
                "minimum_should_match_field": "required_matches"
            }
        }
    }
}
  • 我們也可以使用script腳本來(lái)查詢(xún)
GET /job-candidates/_search
{
    "query": {
        "terms_set": {
            "programming_languages": {
                "terms": ["c++", "java", "php"],
                "minimum_should_match_script": {
                   "source": "Math.min(params.num_terms, doc['required_matches'].value)"
                }
            }
        }
    }
}

range

# 對(duì)數(shù)字進(jìn)行區(qū)間查詢(xún)
GET /product/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 10,
        "lte": 20
      }
    }
  }
}

# 對(duì)時(shí)間進(jìn)行區(qū)間查詢(xún)1
GET /product/_search
{
  "query": {
    "range": {
      "date": {
        "lte": "2020-04-20",
        "gte": "2019-01-01"
      }
    }
  }
}

#對(duì)時(shí)間進(jìn)行區(qū)間查詢(xún)2
# 查找一年以前的數(shù)據(jù)
GET /product/_search
{
  "query": {
    "range": {
      "date": {
        "gte": "now-1y"
      }
    }
  }
}
  • 時(shí)間表達(dá)式
表達(dá)式 釋義
y
M
w
d
H/h 小時(shí)
m 分鐘
s
  • 比較表達(dá)式
表達(dá)式 釋義
gt 大于
gte 大于等于
lt 小于
lte 小于等于

exists

GET /product/_search
{
  "query": {
    "exists": {
      "field": "tag"
    }
  }
}

prefix

前綴查詢(xún)

GET /product/_search
{
  "query": {
    "prefix": {
      "name": {
        "value": "產(chǎn)"
      }
    }
  }
}
  • 查詢(xún)結(jié)果
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "product",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "produceId" : "HKXL-1234-SKOX",
          "name" : "測(cè)試產(chǎn)品1",
          "date" : "2019-05-20",
          "price" : 10
        }
      },
      {
        "_index" : "product",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "produceId" : "UJSK-1234-BSUA",
          "name" : "測(cè)試產(chǎn)品2",
          "price" : 20,
          "date" : "2020-04-15"
        }
      },
      {
        "_index" : "product",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "produceId" : "HSYA-1234-MLBS",
          "name" : "測(cè)試產(chǎn)品3",
          "price" : 40,
          "date" : "2020-01-20"
        }
      },
      {
        "_index" : "product",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.0,
        "_source" : {
          "produceId" : "HSYA-1234-MLBS",
          "name" : "測(cè)試產(chǎn)品4",
          "price" : 40,
          "date" : "2020-01-20",
          "tag" : [
            "機(jī)械"
          ]
        }
      }
    ]
  }
}
  • 等等,不是說(shuō)前綴查詢(xún)嗎,您這也不是前綴查詢(xún)啊,"測(cè)試產(chǎn)品","產(chǎn)"是第三個(gè)詞啊。
  • 嗯,對(duì)于es中的查詢(xún),不能忽略的就是他的分詞結(jié)果,我們?cè)谏厦娲_認(rèn)了它的分詞結(jié)果,是每個(gè)字,單獨(dú)成詞,所以對(duì)于每個(gè)字來(lái)說(shuō),他就是自己的前綴,所以,你搜”測(cè)試產(chǎn)品“中的任意字都是前綴,那如何來(lái)解決呢?大家可以修改分詞器,可以參照我借鑒的文章,有關(guān)分詞器的部分,后續(xù)也會(huì)更新一篇文章// TODO

wildcard

通配符查詢(xún)

  • “*”,它匹配任何字符序列(包括空字符)
  • “?”,它匹配任何單個(gè)字符。
  • 為了防止極慢的通配符查詢(xún),通配符項(xiàng)不應(yīng)以通配符 “*” 或 “?” 開(kāi)頭
GET /product/_search
{
  "query": {
    "wildcard": {
      "name.keyword": {
        "value": "測(cè)試產(chǎn)品?"
      }
    }
  }
}

regexp

正則查詢(xún)

GET /product/_search
{
  "query": {
    "wildcard": {
      "name.keyword": {
        "value": "測(cè)試產(chǎn)品?"
      }
    }
  }
}

我們來(lái)看下它都有哪些操作符【官方直譯】

操作符 釋義 例子
.?????????????????? 匹配任意字符 -
? 重復(fù)0次或1次 abc?
matches 'ab' and 'abc' ???????????????????????????????????????????????????????????????????????????
+ 重復(fù)1次或多次 ab+
matches 'ab', 'abb', 'abbb', ...
* 重復(fù)0次或多次 ab*
matches 'a', 'ab', 'abb', 'abbb', ...
{} 可重復(fù)的最小,最大次數(shù) a{2}
matches 'aa'

a{2,4}
matches 'aa', 'aaa', and 'aaaa'

a{2,}
matches 'a` repeated two or more times
| 如果左邊或右邊最長(zhǎng)的模式匹配,則匹配將成功 abc|xyz
matches 'abc' and 'xyz'
( … ) 形成一個(gè)組??梢允褂媒M將表達(dá)式的一部分視為單個(gè)字符 abc(def)?
matches 'abc' and 'abcdef' but not 'abcd'
[ … ] 1.匹配括號(hào)中的一個(gè)字符
2.在方括號(hào)內(nèi)—表示一個(gè)范圍,除非—是第一個(gè)字符或轉(zhuǎn)義字符
3.方括號(hào)中的字符前的^將使字符或范圍無(wú)效。
1.[abc]
matches 'a', 'b', 'c'

2.[a-c]
matches 'a', 'b', or 'c'

[-abc]
'-' is first character. Matches '-', 'a', 'b', or 'c'

[abc-]
Escapes '-'. Matches 'a', 'b', 'c', or '-'

3.[^abc]
matches any character except 'a', 'b', or 'c'

[^a-c]
matches any character except 'a', 'b', or 'c'

[^-abc]
matches any character except '-', 'a', 'b', or 'c'

[^abc-]
matches any character except 'a', 'b', 'c', or '-'

我們可以使用flags參數(shù)為L(zhǎng)ucene的正則表達(dá)式引擎啟用更多的可選操作符。要啟用多個(gè)操作符,使用|分隔符

GET /product/_search
{
    "query": {
        "regexp":{
            "name.keyword": {
                "value": "測(cè).+&.+試.*",
                "flags" : "INTERSECTION"
            }
        }
    }
}

我們看下flags都有哪些類(lèi)型

操作符 釋義 例子
ALL 啟用所有可選操作 -
COMPLEMENT 啟用~操作 a~bc
matches 'adc' and 'aec' but not 'abc'
INTERVAL 啟用<>操作,可以用作匹配一個(gè)數(shù)字的區(qū)間 foo<1-100>
matches 'foo1', 'foo2' ... 'foo99', 'foo100'

foo<01-100>
matches 'foo01', 'foo02' ... 'foo99', 'foo100'
INTERSECTION 啟用&操作,相當(dāng)于AND aaa.+&.+bbb
matches 'aaabbb'
ANYSTRING 啟用@操作 @&~(abc.+)
matches everything except terms beginning with 'abc'

fuzzy

模糊查詢(xún)

# 添加三篇測(cè)試文檔
PUT /fuzz/_doc/1
{
  "name": "sunruikai 123"
}

PUT /fuzz/_doc/2
{
  "name": "gabriella 456"
}

PUT /fuzz/_doc/3
{
  "name": "test kak"
}
  • 執(zhí)行查詢(xún)
GET /fuzz/_search
{
  "query": {
    "fuzzy": {
      "name": {
        "value": "sunruilai"
      }
    }
  }
}

當(dāng)然,除了value它還有其他屬性

屬性 釋義
fuzziness ??????????????????????????????????????????????????????????????????????? 允許匹配的最大編輯距離
max_expansions 查詢(xún)中的詞項(xiàng)可以擴(kuò)展的數(shù)目,默認(rèn)為50【避免在max_expansions參數(shù)中使用高值,特別是當(dāng)prefix_length參數(shù)值為0時(shí)。max_expansions參數(shù)中的高值會(huì)導(dǎo)致性能低下,因?yàn)橐獧z查的變量太多?!?/td>
prefix_length 指明區(qū)分詞項(xiàng)的共同前綴長(zhǎng)度,默認(rèn)是0
transpositions 表示編輯是否包含兩個(gè)相鄰字符的移位(ab→ba),默認(rèn)為true
rewrite 有6中方式,constant_score(默認(rèn)),constant_score_boolean,scoring_boolean,top_terms_blended_freqs_N,top_terms_boost_N,top_terms_N

ids

見(jiàn)名知意,就是通過(guò)一堆id進(jìn)行查詢(xún)

GET /product/_search
{
  "query": {
    "ids": {
      "values": [1,2,3]
    }
  }
}

costanct_score

不計(jì)算得分

GET /product/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "produceId.keyword": "HKXL-1234-SKOX"
        }
      }
    }
  }
}

3. 大功告成

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容