文章目錄
1. 回顧上節內容
上一節中,完成了Elasticsearch 基礎概念,以及安裝與簡單查詢,那麼在更復雜的查詢操作場景下我們應該如何操作呢?本節之後就能夠完成對es的更復雜操作
2. 查詢
在關係型數據庫中操作數據的語句爲SQL,在 Elasticsearch 中採用 領域特定語言 (DSL)
, 使用 JSON 構造了一個請求 .
上節中查詢全部的數據爲:
GET /megacorp/employee/_search
查詢特定條件,如:
2.1 查詢所有名字爲Smith的結果
GET /megacorp/employee/_search
{
"query" : {
"match" : {
"last_name" : "Smith"
}
}
}
與之前的不同是添加了json方法體
:
query
代表這是一個查詢match
代表查詢類型last_name:smith
要查詢的屬性
與值
2.2 姓名與年齡複合查詢
搜索姓氏爲 Smith 的員工,但這次我們只需要年齡大於 30 的
GET /megacorp/employee/_search
{
"query" : {
"bool": {
"must": {
"match" : {
"last_name" : "smith"
}
},
"filter": {
"range" : {
"age" : { "gt" : 30 }
}
}
}
}
}
可以看到這次查詢明顯不同,
- 結構嵌套更深
- 關鍵詞更多
- 不同數據類型的查詢
那麼這些不同的關鍵詞代表什麼含義呢?
DSL查詢語言中存在兩種:查詢DSL(query DSL)和過濾DSL(filter DSL)。
首先,多條條件合併搜索需要使用bool
, 然後 兩個條件同級: must
代表其中條件必須全部成立,雖然這裏只有一條 , filter
它支持高效地執行一個結構化查詢 range
它能找到年齡大於 30 的文檔,其中 gt
表示 大於(great than)。
2.3 全文搜索
前面兩個都是強關聯的數據如姓名相等,年齡過濾,現在需要提供全文搜索,搜索所以喜歡攀巖(rock climbing)的員工
GET /megacorp/employee/_search
{
"query" : {
"match" : {
"about" : "rock climbing"
}
}
}
顯然我們依舊使用之前的 match 查詢在about
屬性上搜索 “rock climbing” 。得到兩個匹配的文檔
雖然 Jane Smith
的興趣不是完全匹配但是也返回了,但是得到的匹配度得分_score
比完全匹配低,這是與關係數據庫完全不同的概念相關性
2.4 短語搜索
找出一個屬性中的獨立單詞是沒有問題,如果需要精確匹配一系列單詞或者短語
比如, 我們想執行這樣一個查詢,僅匹配同時包含 “rock” 和 “climbing” ,並且 二者以短語 “rock climbing” 的形式緊挨着的僱員記錄
GET /megacorp/employee/_search
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
}
}
因此,使用 match_phrase
可以完成這種需求 , 因此它只返回一條
2.5 高亮顯示
在使用搜索引擎時經常會有搜索結果中標出搜索關鍵詞,我們只需要添加highlight
參數即可
GET /megacorp/employee/_search
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
},
"highlight": {
"fields" : {
"about" : {}
}
}
}
在返回的結果 , 有多出highlight
部分 其中包含的about
屬性匹配的文本使用<em></em>
包裹
{
...
"hits": {
"hits": [
{
...
"_source": {
...
"about": "I love to go rock climbing",
"interests": [
"sports",
"music"
]
},
"highlight": {
"about": [
"I love to go <em>rock</em> <em>climbing</em>"
]
}
}
]
}
}
2.6 聚合函數
終於到了最後一個業務需求:支持管理者對員工目錄做分析
。
Elasticsearch 有一個功能叫聚合(aggregations),允許我們基於數據生成一些精細的分析結果。聚合與 SQL 中的 GROUP BY 類似但更強大。
舉個例子,挖掘出員工中最受歡迎的興趣愛好:
GET /megacorp/employee/_search
{
"aggs": {
"all_interests": {
"terms": {
"field": "interests"
}
}
}
}
當然如果你是按步驟過來是查詢不到的,這裏需要開啓聚合
PUT megacorp/_mapping/employee/
{
"properties": {
"interests": {
"type": "text",
"fielddata": true
}
}
}
得到結果
"buckets": [
{
"key": "music",
"doc_count": 2
},
{
"key": "forestry",
"doc_count": 1
},
{
"key": "sports",
"doc_count": 1
}
]
同時聚合也可以根據搜索結果聚合,如先篩選名字叫Smith的員工中的興趣愛好
GET /megacorp/employee/_search
{
"query": {
"match": {
"last_name": "smith"
}
},
"aggs": {
"all_interests": {
"terms": {
"field": "interests"
}
}
}
}
聚合還支持分級彙總
比如,查詢特定興趣愛好員工的平均年齡
GET /megacorp/employee/_search
{
"aggs" : {
"all_interests" : {
"terms" : { "field" : "interests" },
"aggs" : {
"avg_age" : {
"avg" : { "field" : "age" }
}
}
}
}
}
3. 額外擴展
到這,基本上我們能夠插入並搜索,雖然搜索只學了幾種特殊的結構以及關鍵詞,這裏也是跟着官方教程走,當然肯定有些內容是目前無法理解的,例如各種關鍵詞間的組合,這在後面會有詳細的講解,這裏再補充幾點搜索中使用的關鍵詞及其作用
3.1 bool 聯合查詢: must, should, must_not
- must: 文檔必須完全多個匹配條件
與
- should: should下面會帶一個以上的條件,至少滿足一個條件
或
- must_not: 文檔必須不匹配多個條件-
非
注意 在es中搜索都是以
詞
爲單位,例如prefix 前綴匹配
內容hello world
搜索關鍵詞wo
也能顯示搜索得到 ,同時有些關鍵詞搜索也會進行分詞,如match
搜索關鍵詞hello world
會搜索hello
或者world
的內容,需要保持順序應該使用match_phase
,不分詞應該使用term
同時,es中分詞後默認英文索引是小寫,需要大小寫敏感需要額外設置
我開始就是沒有理解
分詞
的概念 , 所以實驗網上的語句,一直莫名查不出來
3.2 檢索語法分析:match,match_phrase,term, wildcard, prefix, fuzzy, range, query_string, text, missing
match: 類似於與
首先對內容分詞 然後查詢所以分詞(一個也算)包含的結果
例如: 文檔
hello
hello world
, 檢索h
沒有內容,hello
兩個都能匹配hello world
兩個都能匹配
match_phrase: 與match 相同,但是隻返回與檢索內容相同順序的詞的文檔
例如: 文檔
hello world
world hello
is hello world
檢索hello world
只能匹配1,3
term:嚴格匹配條件,所查詢的字段內容要與填入查詢框搜索值一致,同時不對檢索內容分詞,因此如果查詢內容長的話,不分詞是不能匹配到結果的
例如: 文檔
fir hello
搜索hello
可以找到 但搜索fir hello
不能找到 , 因爲不會分詞 所以後面查詢倒排索引的分詞結果是沒有匹配的
wildcard:通配符查詢,* 表示全匹配,? 表示單一匹配,不對檢索內容分詞
,會檢索所以的倒排索引,性能不佳
例如: 文檔
hello world
fir hello
,檢索h*
都能找到 , 檢索h?
都不能 ,檢索fir hello
都不能
prefix:前綴匹配,以什麼開頭 ,不對檢索內容分詞
例如: 文檔
hello world
,檢索w
可以找到 , 檢索h
可以找到
fuzzy 是彈性模糊匹配,有兩種匹配模式 , 比較複雜後面單獨講解
- min_similarity
- max_expansions
range:範圍查詢數值或日期,gt爲大於,gte爲大於等於,lt小於,lte小於等於,所搜索的字段值在兩個搜索框標識數值之間;
query_string:字符片段查詢,如果是數字,則嚴格匹配數字,如果是字符串,則按照自身或者分片詞匹配;
text:分片詞查詢,等確定後更新;
missing:查詢沒有定義該字段或者該字段值爲null的數據。
注意: 在對搜索的屬性中 5.x之後有
text
keyword
之分 , 所以上述中的情況都是在text
的情況下,會對文檔屬性分詞 ,keyword
不會對文檔屬性分詞
舉個例子:文檔Fir Hello
Fir
text 情況下term
搜索Fir
不能搜索到,搜索fir
搜索到兩個,搜索fir hello
不能搜索到 搜索hello
只能搜索到第一個
keyword 情況下term
搜索fir
不能搜索到,搜索Fir
第二個,Fir Hello
只能搜索第一個