Elasticsearch入門到精通第二篇-查詢分析

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 } 
                }
            }
        }
    }
}

可以看到這次查詢明顯不同,

  1. 結構嵌套更深
  2. 關鍵詞更多
  3. 不同數據類型的查詢

那麼這些不同的關鍵詞代表什麼含義呢?

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只能搜索第一個

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章