ElasticSearch結構化搜索和全文搜索

一、結構化搜索

1.1 精確值查找

過濾器很重要,由於它們執行速度很是快,不會計算相關度(直接跳過了整個評分階段)並且很容易被緩存。請儘量多的使用過濾式查詢。html

term 查詢會查找咱們指定的精確值。做爲其自己, term 查詢是簡單的。它接受一個字段名以及咱們但願查找的數值:
{緩存

"term" : {
    "price" : 20
}

}less

一般當查找一個精確值的時候,咱們不但願對查詢進行評分計算。只但願對文檔進行包括或排除的計算,因此咱們會使用 constant_score 查詢以非評分模式來執行 term 查詢並以一做爲統一評分。由於在查詢時,不須要計算評分,所以採用constant_score尋找的方式速度會更快。
最終組合的結果是一個 constant_score 查詢,它包含一個 term 查詢:elasticsearch

GET /my_store/products/_search
{
  "query" : {
      "constant_score" : { 
          "filter" : {
              "term" : { 
                  "price" : 20
              }
          }
      }
  }
}

1.2 組合過濾器

1.2.1 布爾過濾器

{
   "bool" : {
      "must" :     [],
      "should" :   [],
      "must_not" : [],
   }
}

must
全部的語句都 必須(must) 匹配,與 AND 等價。
must_not
全部的語句都 不能(must not) 匹配,與 NOT 等價。
should
至少有一個語句要匹配,與 OR 等價。


GET /my_store/products/_search
{
   "query" : {
      "filtered" : { 
         "filter" : {
            "bool" : {
              "should" : [
                 { "term" : {"price" : 20}}, 
                 { "term" : {"productID" : "XHDK-A-1293-#fJ3"}} 
              ],
              "must_not" : {
                 "term" : {"price" : 30} 
              }
           }
         }
      }
   }
}

1.2.2 嵌套布爾過濾器

SELECT document
FROM   products
WHERE  productID      = "KDKE-B-9947-#kL5"
  OR (     productID = "JODL-X-1937-#pV7"
       AND price     = 30 )

GET /my_store/products/_search
{
   "query" : {
      "filtered" : {
         "filter" : {
            "bool" : {
              "should" : [
                { "term" : {"productID" : "KDKE-B-9947-#kL5"}}, 
                { "bool" : { 
                  "must" : [
                    { "term" : {"productID" : "JODL-X-1937-#pV7"}}, 
                    { "term" : {"price" : 30}} 
                  ]
                }}
              ]
           }
         }
      }
   }
}

1.3 查找多個精確值

若是咱們想要查找價格字段值爲 $20 或 $30 的文檔該如何處理呢?
GET /my_store/products/_search
{
    "query" : {
        "constant_score" : {
            "filter" : {
                "terms" : { 
                    "price" : [20, 30]
                }
            }
        }
    }
}

1.4 範圍

gt: > 大於(greater than)
lt: < 小於(less than)
gte: >= 大於或等於(greater than or equal to)
lte: <= 小於或等於(less than or equal to)

GET /my_store/products/_search
{
    "query" : {
        "constant_score" : {
            "filter" : {
                "range" : {
                    "price" : {
                        "gte" : 20,
                        "lt"  : 40
                    }
                }
            }
        }
    }
}

若是想要範圍無界(比方說 >20 ),只須省略其中一邊的限制:
"range" : {
    "price" : {
        "gt" : 20
    }
}

日期範圍
"range" : {
    "timestamp" : {
        "gt" : "2014-01-01 00:00:00",
        "lt" : "2014-01-07 00:00:00"
    }
}

當使用它處理日期字段時, range 查詢支持對 日期計算(date math) 進行操做,比方說,若是咱們想查找時間戳在過去一小時內的全部文檔:
"range" : {
    "timestamp" : {
        "gt" : "now-1h"
    }
}

"range" : {
    "timestamp" : {
        "gt" : "2014-01-01 00:00:00",
        "lt" : "2014-01-01 00:00:00||+1M" 
    }
}

1.5 處理null值

1.5.1 存在查詢

SELECT tags
FROM   posts
WHERE  tags IS NOT NULL

GET /my_index/posts/_search
{
    "query" : {
        "constant_score" : {
            "filter" : {
                "exists" : { "field" : "tags" }
            }
        }
    }
}

1.5.2.缺失查詢

SELECT tags
FROM   posts
WHERE  tags IS NULL

GET /my_index/posts/_search
{
    "query" : {
        "constant_score" : {
            "filter": {
                "missing" : { "field" : "tags" }
            }
        }
    }
}

二、 全文搜索

2.1 匹配查詢

match 是個 核心 查詢。不管須要查詢什麼字段, match 查詢都應該會是首選的查詢方式。 它是一個高級 全文查詢 ,這表示它既能處理全文字段,又能處理精確字段。match 查詢主要的應用場景就是進行全文搜索。ide

2.1.1. 單個詞查詢

GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": "QUICK!"
        }
    }
}

2.1.2 多個詞查詢

GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": "BROWN DOG!"
        }
    }
}

用 任意 查詢詞項匹配文檔可能會致使結果中出現不相關的長尾。 這是種散彈式搜索。可能咱們只想搜索包含 全部 詞項的文檔,也就是說,不去匹配 brown OR dog ,而經過匹配 brown AND dog 找到全部文檔。post

match 查詢還能夠接受 operator 操做符做爲輸入參數,默認狀況下該操做符是 or 。咱們能夠將它修改爲 and 讓全部指定詞項都必須匹配:ui

GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": {      
                "query":    "BROWN DOG!",
                "operator": "and"
            }
        }
    }
}

2.2 組合查詢

GET /my_index/my_type/_search
{
  "query": {
    "bool": {
      "must":     { "match": { "title": "quick" }},
      "must_not": { "match": { "title": "lazy"  }},
      "should": [
                  { "match": { "title": "brown" }},
                  { "match": { "title": "dog"   }}
      ]
    }
  }
}

2.3 控制精度

就像咱們能控制 match 查詢的精度 同樣,咱們能夠經過 minimum_should_match 參數控制須要匹配的 should 語句的數量, 它既能夠是一個絕對的數字,又能夠是個百分比:code

GET /my_index/my_type/_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "title": "brown" }},
        { "match": { "title": "fox"   }},
        { "match": { "title": "dog"   }}
      ],
      "minimum_should_match": 2 
    }
  }
}

這個查詢結果會將全部知足如下條件的文檔返回: title 字段包含 "brown" AND "fox" 、 "brown" AND "dog" 或 "fox" AND "dog" 。若是有文檔包含全部三個條件,它會比只包含兩個的文檔更相關。htm

2.4 查詢語句提高權重

假設想要查詢關於 「full-text search(全文搜索)」 的文檔, 但咱們但願爲說起 「Elasticsearch」 或 「Lucene」 的文檔給予更高的 權重 ,這裏 更高權重 是指若是文檔中出現 「Elasticsearch」 或 「Lucene」 ,它們會比沒有的出現這些詞的文檔得到更高的相關度評分 _score ,也就是說,它們會出如今結果集的更上面。排序

GET /_search
{
    "query": {
        "bool": {
            "must": {
                "match": {
                    "content": { 
                        "query":    "full text search",
                        "operator": "and"
                    }
                }
            },
            "should": [ 
                { "match": { "content": "Elasticsearch" }},
                { "match": { "content": "Lucene"        }}
            ]
        }
    }
}


should 語句匹配得越多表示文檔的相關度越高。目前爲止還挺好。

可是若是咱們想讓包含 Lucene 的有更高的權重,而且包含 Elasticsearch 的語句比 Lucene 的權重更高,該如何處理?

咱們能夠經過指定 boost 來控制任何查詢語句的相對的權重, boost 的默認值爲 1 ,大於 1 會提高一個語句的相對權重。因此下面重寫以前的查詢:
GET /_search
{
    "query": {
        "bool": {
            "must": {
                "match": {  
                    "content": {
                        "query":    "full text search",
                        "operator": "and"
                    }
                }
            },
            "should": [
                { "match": {
                    "content": {
                        "query": "Elasticsearch",
                        "boost": 3 
                    }
                }},
                { "match": {
                    "content": {
                        "query": "Lucene",
                        "boost": 2 
                    }
                }}
            ]
        }
    }
}

三、展望

在使用ES的過程當中在網上搜到了一些ES封裝的第三方擴展類,但並未找到在項目中對第三方擴展類進一步封裝更加友好地在項目中使用的PHP封裝類,所以打算自定義一個ES服務類,目前正在開發中,於是熟悉文檔並進行概括總結即是第一步,接下來完成以後便更新發布。目前的思路爲對於經常使用的查詢操做,封裝一個方法便可,並支持傳入參數查詢字段、排序,分頁。相似like方式的搜索單獨寫一個方法,並能夠支持高亮顯示搜索詞。對於複雜的可直接支持原生方式查詢。

附錄

參考文檔地址

相關文章
相關標籤/搜索