1. 程式人生 > >Elasticsearch 常用基本查詢

Elasticsearch 常用基本查詢

https://www.cnblogs.com/sunfie/p/6653778.html

 

Elasticsearch 常用基本查詢

安裝啟動很簡單,參考官網步驟:https://www.elastic.co/downloads/elasticsearch

  為了介紹Elasticsearch中的不同查詢型別,我們將對帶有下列欄位的文件進行搜尋:title(標題),authors(作者),summary(摘要),release date(釋出時間)以及number of reviews(評論數量),首先,讓我們建立一個新的索引,並通過bulk API查詢文件:  

  為了展示Elasticsearch中不同查詢的用法,首先在Elasticsearch裡面建立了employee相關的documents,每本書主要涉及以下欄位: first_name, last_name, age,about,interests,操作如下:

1 curl -XPUT 'localhost:9200/megacorp/employee/3' -d '{ "first_name" : "Douglas", "last_name" : "Fir", "age" : 35, "about" : "I like to build cabinets", "interests": "forestry" }'
2 curl -XPUT 'localhost:9200/megacorp/employee/2' -d '{ "first_name" : "Jane", "last_name" : "Smith", "age" : 32, "about" : "I like to collect rock albums", "interests": "music" }'
3 curl -XPUT 'localhost:9200/megacorp/employee/1' -d '{ "first_name" : "John", "last_name" : "Smith", "age" : 25, "about" : "I love to go rock climbing", "interests": [ "sports", "music" ] }'

1. 基本匹配查詢(Basic Match Query)

  基本匹配查詢主要有兩種形式:(1)使用Search Lite API,並將所有的搜尋引數都通過URL傳遞;

                (2)使用Elasticsearch DSL,其可以通過傳遞一個JSON請求來獲取結果。下面是在所有的欄位中搜索帶有"John"的結果

1 curl -XGET 'localhost:9200/megacorp/employee/_search?q=John'

如果我們使用Query DSL來展示出上面一樣的結果可以這麼來寫:

複製程式碼

curl -XGET 'localhost:9200/megacorp/_search' -d '
{
    "query": {
        "multi_match" : {
            "query" : "John",
            "fields" : ["_all"]
        }
    }
}'

複製程式碼

  其輸出和上面使用/_search?q=john的輸出一樣。上面的multi_match關鍵字通常在查詢多個fields的時候作為match關鍵字的簡寫方式。fields屬性指定需要查詢的欄位,如果我們想查詢所有的欄位,這時候可以使用_all關鍵字,正如上面的一樣。以上兩種方式都允許我們指定查詢哪些欄位。比如,我們想查詢interest中出現music的員工,那麼我們可以這麼查詢:

1 curl -XGET 'localhost:9200/megacorp/employee/_search?q=interests:music'

  然而,DSL方式提供了更加靈活的方式來構建更加複雜的查詢(我們將在後面看到),甚至指定你想要的返回結果。下面的例子中,我將指定需要返回結果的數量,開始的偏移量(這在分頁的情況下非常有用),需要返回document中的哪些欄位以及高亮關鍵字:

curl -XGET 'localhost:9200/megacorp/employee/_search?pretty' -d '{"query": { "match" : { "interests" : "music" }},"size": 2,"from": 0,"_source": [ "first_name", "last_name", "interests" ],"highlight": {"fields" : { "interests" : { } } } }'

  需要注意的是:對於查詢多個關鍵字,match關鍵字允許我們使用and操作符來代替預設的or操作符。你也可以指定minimum_should_match操作符來調整返回結果的相關性(tweakrelevance)。

2. Multi-field Search

  正如我們之前所看到的,想在一個搜尋中查詢多個 document field (比如使用同一個查詢關鍵字同時在title和summary中查詢),你可以使用multi_match查詢,使用如下:

複製程式碼

curl -XGET 'localhost:9200/megacorp/employee/_search' -d '
{
    "query": {
        "multi_match" : {
            "query" : "rock",
            "fields": ["about", "interests"]
        }
    }
}'

複製程式碼

3. Boosting
  我們上面使用同一個搜尋請求在多個field中查詢,你也許想提高某個field的查詢權重,在下面的例子中,我們把interests的權重調成3,這樣就提高了其在結果中的權重,這樣把_id=4的文件相關性大大提高了,如下:

複製程式碼

curl -XGET 'localhost:9200/megacorp/employee/_search' -d '
{
    "query": {
        "multi_match" : {
            "query" : "rock",
            "fields": ["about", "interests^3"]
        }
    }
}'

複製程式碼

Boosting不僅僅意味著計算出來的分數(calculated score)直接乘以boost factor,最終的boost value會經過歸一化以及其他一些內部的優化

4. Bool Query
  我們可以在查詢條件中使用AND/OR/NOT操作符,這就是布林查詢(Bool Query)。布林查詢可以接受一個must引數(等價於AND),一個must_not引數(等價於NOT),以及一個should引數(等價於OR)。比如,我想查詢about中出現music或者climb關鍵字的員工,員工的名字是John,但姓氏不是smith,我們可以這麼來查詢:

複製程式碼

curl -XGET 'localhost:9200/megacorp/employee/_search' -d '
{
    "query": {
        "bool": {
                "must": {
                    "bool" : { 
                        "should": [
                            { "match": { "about": "music" }},
                            { "match": { "about": "climb" }} ] 
                    }
                },
                "must": {
                    "match": { "first_nale": "John" }
                },
                "must_not": {
                    "match": {"last_name": "Smith" }
                }
            }
    }
}'

複製程式碼

5. Fuzzy Queries(模糊查詢)

   模糊查詢可以在Match和 Multi-Match查詢中使用以便解決拼寫的錯誤,模糊度是基於Levenshteindistance計算與原單詞的距離。使用如下:

複製程式碼

curl -XGET 'localhost:9200/megacorp/employee/_search' -d '
{
    "query": {
        "multi_match" : {
            "query" : "rock climb",
            "fields": ["about", "interests"],
            "fuzziness": "AUTO"
        }
    },
    "_source": ["about", "interests", "first_name"],
    "size": 1
}'

複製程式碼

  上面我們將fuzziness的值指定為AUTO,其在term的長度大於5的時候相當於指定值為2,然而80%的人拼寫錯誤的編輯距離(edit distance)為1,所有如果你將fuzziness設定為1可能會提高你的搜尋效能

 6. Wildcard Query(萬用字元查詢)

  萬用字元查詢允許我們指定一個模式來匹配,而不需要指定完整的trem。?將會匹配如何字元;*將會匹配零個或者多個字元。比如我們想查詢所有名字中以J字元開始的記錄,我們可以如下使用:

複製程式碼

curl -XGET 'localhost:9200/megacorp/employee/_search' -d '
{
    "query": {
            "wildcard" : {
                "first_name" : "s*"
            }
        },
        "_source": ["first_name", "last_name"],
    "highlight": {
            "fields" : {
                "first_name" : {}
            }
        }
}'

複製程式碼

7. Regexp Query(正則表示式查詢)
  ElasticSearch還支援正則表示式查詢,此方式提供了比萬用字元查詢更加複雜的模式。比如我們先查詢作者名字以J字元開頭,中間是若干個a-z之間的字元,並且以字元n結束的記錄,可以如下查詢:

複製程式碼

curl -XGET 'localhost:9200/megacorp/employee/_search' -d '
{
    "query": {
        "regexp" : {
            "first_name" : "J[a-z]*n"
        }
    },
    "_source": ["first_name", "age"],
    "highlight": {
        "fields" : {
            "first_name" : {}
        }
    }
}'

複製程式碼

8. Match Phrase Query(匹配短語查詢)
  匹配短語查詢要求查詢字串中的trems要麼都出現Document中、要麼trems按照輸入順序依次出現在結果中。在預設情況下,查詢輸入的trems必須在搜尋字串緊挨著出現,否則將查詢不到。不過我們可以指定slop引數,來控制輸入的trems之間有多少個單詞仍然能夠搜尋到,如下所示:

複製程式碼

curl -XGET 'localhost:9200/megacorp/employee/_search' -d '
{
    "query": {
        "multi_match": {
            "query": "climb rock",
            "fields": [
                "about",
                "interests"
            ],
            "type": "phrase",
            "slop": 3
        }
    },
    "_source": [
        "title",
        "about",
        "interests"
    ]
}'

複製程式碼

  從上面的例子可以看出,id為4的document被搜尋(about欄位裡面精確匹配到了climb rock),並且分數比較高;而id為1的document也被搜尋到了,雖然其about中的climb和rock單詞並不是緊挨著的,但是我們指定了slop屬性,所以被搜尋到了。如果我們將"slop":3條件刪除,那麼id為1的文件將不會被搜尋到。

9. Match Phrase Prefix Query(匹配短語字首查詢)
  匹配短語字首查詢可以指定單詞的一部分字元字首即可查詢到該單詞,和match phrase query一樣我們也可以指定slop引數;同時其還支援max_expansions引數限制被匹配到的terms數量來減少資源的使用,使用如下:

複製程式碼

curl -XGET 'localhost:9200/megacorp/employee/_search' -d '
{
    "query": {
        "match_phrase_prefix": {
            "summary": {
                "query": "cli ro",
                "slop": 3,
                "max_expansions": 10
            }
        }
    },
    "_source": [
        "about",
        "interests",
        "first_name"
    ]
}'

複製程式碼

10. Query String
  query_string查詢提供了一種手段可以使用一種簡潔的方式執行multi_match queries, bool queries, boosting, fuzzy matching, wildcards, regexp以及range queries的組合查詢。在下面的例子中,我們運行了一個模糊搜尋(fuzzy search),搜尋關鍵字是search algorithm,並且作者包含grant ingersoll或者tom morton。並且搜尋了所有的欄位,其中summary欄位的權重為2:

複製程式碼

curl -XGET 'localhost:9200/megacorp/employee/_search' -d '
{
    "query": {
        "query_string" : {
            "query": "(saerch~1 algorithm~1) AND (grant ingersoll) OR (tom morton)",
            "fields": ["_all", "summary^2"]
        }
    },
    "_source": [ "title", "summary", "authors" ],
    "highlight": {
        "fields" : {
            "summary" : {}
        }
    }
}'

複製程式碼

11. Simple Query String(簡單查詢字串)
  simple_query_string是query_string的另一種版本,其更適合為使用者提供一個搜尋框中,因為其使用+/|/- 分別替換AND/OR/NOT,如果用輸入了錯誤的查詢,其直接忽略這種情況而不是丟擲異常。使用如下:

複製程式碼

curl -POST 'localhost:9200/megacorp/employee/_search' -d '
{
    "query": {
        "simple_query_string" : {
        "query": "(saerch~1 algorithm~1) + (grant ingersoll) | (tom morton)",
        "fields": ["_all", "summary^2"]
        }
    },
    "_source": [ "title", "summary", "authors" ],
    "highlight": {
        "fields" : {
            "summary" : {}
        }
    }
}'

複製程式碼

12. Term/Terms Query
  前面的例子中我們已經介紹了全文搜尋(full-text search),但有時候我們對結構化搜尋中能夠精確匹配並返回搜尋結果更感興趣。這種情況下我們可以使用term和terms查詢。在下面例子中,我們想搜尋所有興趣中有music的人:

複製程式碼

curl -POST 'localhost:9200/megacorp/employee/_search' -d '
{
    "query": {
        "term" : {
            "interests": "music"
        }
    },
    "_source" : ["first_name","last_name","interests"]
}'

複製程式碼

我們還可以使用terms關鍵字來指定多個terms,如下:

複製程式碼

{
    "query": {
        "terms" : {
            "publisher": ["oreilly", "packt"]
        }
    }
}

複製程式碼

13. Term Query - Sorted

  查詢結果和其他查詢結果一樣可以很容易地對其進行排序,而且我們可以對輸出結果按照多層進行排序:

複製程式碼

curl -XPOST 'localhost:9200/megacorp/employee/_search' -d '
{
    "query": {
        "term" : {
            "interests": "music"
        }
    },
    "_source" : ["interests","first_name","about"],
    "sort": [
        { "publish_date": {"order":"desc"}},
        { "id": { "order": "desc" }}
    ]
}'

複製程式碼

14. Range Query(範圍查詢)
另一種結構化查詢就是範圍查詢。在下面例子中,我們搜尋所有發行年份為2015的圖書:

複製程式碼

curl -XPOST 'localhost:9200/person/worker/_search?pretty' -d '
{
    "query": {
        "range" : {
            "birthday": {
                "gte": "2017-02-01",
                "lte": "2017-05-01"
            }
        }
    },
    "_source" : ["first_name","last_name","birthday"]
}'

複製程式碼

範圍查詢可以應用於日期,數字以及字元型別的欄位。

 

15. Filtered Query(過濾查詢)
  過濾查詢允許我們對查詢結果進行篩選。比如:我們查詢about和interests中包含music關鍵字的員工,但是我們想過濾出birthday大於2017/02/01的結果,可以如下使用:

複製程式碼

curl -XPOST :9200/megacorp/employee/_search?pretty' -d '
{
    "query": {
        "filtered": {
            "query" : {
                "multi_match": {
                    "query": "music",
                    "fields": ["about","interests"]
                }
            },
            "filter": {
                "range" : {
                    "birthday": {
                        "gte": 2017-02-01
                    }
                }
            }
        }
    },
    "_source" : ["first_name","last_name","about", "interests"]
}'

複製程式碼

注意:過濾查詢(Filtered queries)並不強制過濾條件中指定查詢,如果沒有指定查詢條件,則會執行match_all查詢,其將會返回index中所有文件,然後對其進行過濾,在實際運用中,過濾器應該先被執行,這樣可以減少需要查詢的範圍,而且,第一次使用fliter之後其將會被快取,這樣會對效能代理提升。Filtered queries在即將發行的Elasticsearch 5.0中移除了,我們可以使用bool查詢來替換他,下面是使用bool查詢來實現上面一樣的查詢效果,返回結果一樣:

複製程式碼

curl -XPOST 'localhost:9200/megacorp/employee/_search?pretty' -d '
{
    "query": {
        "bool": {
            "must" : {
                "multi_match": {
                    "query": "music",
                    "fields": ["about","interests"]
                }
            },
            "filter": {
                "range" : {
                    "birthday": {
                        "gte": 2017-02-01
                    }
                }
            }
        }
    },
    "_source" : ["first_name","last_name","about", "interests"]
}'

複製程式碼

16. Multiple Filters(多過濾器查詢)
  多過濾器查詢可以通過結合使用bool過濾查詢實現。下面的示例中,我們將篩選出返回的結果必須至少有20條評論,必須是在2015年之前釋出的,而且應該是由O'Reilly出版的,首先建立索引iteblog_book_index並向其插入資料,如下所示:

複製程式碼

curl -XPOST 'localhost:9200/iteblog_book_index/book/1' -d '{ "title": "Elasticsearch: The Definitive Guide", "authors": ["clinton gormley", "zachary tong"], "summary" : "A distibuted real-time search and analytics engine", "publish_date" : "2015-02-07","num_reviews": 20, "publisher": "oreilly" }'
curl -XPOST 'localhost:9200/iteblog_book_index/book/2' -d '{ "title": "Taming Text: How to Find, Organize, and Manipulate It", "authors": ["grant ingersoll", "thomas morton", "drew farris"], "summary" : "organize text using approaches such as full-text search, proper name recognition, clustering, tagging, information extraction, and summarization", "publish_date" : "2013-01-24", "num_reviews": 12, "publisher": "manning" }'
curl -XPOST 'localhost:9200/iteblog_book_index/book/3' -d '{ "title": "Elasticsearch in Action", "authors": ["radu gheorge", "matthew lee hinman", "roy russo"], "summary" : "build scalable search applications using Elasticsearch without having to do complex low-level programming or understand advanced data science algorithms", "publish_date" : "2015-12-03", "num_reviews": 18, "publisher": "manning" }'
curl -XPOST 'localhost:9200/iteblog_book_index/book/4' -d '{ "title": "Solr in Action", "authors": ["trey grainger", "timothy potter"], "summary" : "Comprehensive guide to implementing a scalable search engine using Apache Solr", "publish_date" : "2014-04-05", "num_reviews": 23, "publisher": "manning" }'

複製程式碼

然後執行如下查詢語句:

複製程式碼

curl -XPOST 'localhost:9200/iteblog_book_index/book/_search?pretty' -d '
{
    "query": {
        "filtered": {
            "query" : {
                "multi_match": {
                "query": "elasticsearch",
                "fields": ["title","summary"]
                }
            },
            "filter": {
                "bool": {
                    "must": {
                        "range" : { "num_reviews": { "gte": 20 } }
                    },
                    "must_not": {
                        "range" : { "publish_date": { "lte": "2014-12-31" } }
                    },
                    "should": {
                        "term": { "publisher": "oreilly" }
                    }
                }
            }
        }
    },
    "_source" : ["title","summary","publisher", "num_reviews", "publish_date"]
}'

複製程式碼

17. Function Score: Field Value Factor
  在某些場景下,你可能想對某個特定欄位設定一個因子(factor),並通過這個因子計算某個文件的相關度(relevance score)。這是典型地基於文件(document)的重要性來擡高其相關性的方式。在下面例子中,我們想找到更受歡迎的圖書(是通過圖書的評論實現的),並將其權重擡高,這裡可以通過使用field_value_factor來實現

複製程式碼

curl -XPOST 'localhost:9200/iteblog_book_index/book/_search?pretty' -d '
{
    "query": {
        "function_score": {
            "query": {
                "multi_match" : {
                    "query" : "search engine",
                    "fields": ["title", "summary"]
                }
            },
            "field_value_factor": {
                "field" : "num_reviews",
                "modifier": "log1p",
                "factor" : 2
            }
        }
    },
    "_source": ["title", "summary", "publish_date", "num_reviews"]
}'

複製程式碼