1. 程式人生 > >ElasticSearch 7.X版本19個常用的查詢語句

ElasticSearch 7.X版本19個常用的查詢語句

------ 整理一篇常用的CRUD查詢語句,之前這篇檔案是在17年左右發表的,從英文翻譯過來,現在採用7.x 版本進行實驗,棄用的功能或者引數,我這邊會進行更新,一起來學習吧。 為了演示不同型別的 **ElasticSearch** 的查詢,我們將使用書文件資訊的集合(有以下欄位:**title**(標題), **authors**(作者), **summary**(摘要), **publish_date**(釋出日期)和 **num_reviews**(瀏覽數))。 在這之前,首先我們應該先建立一個新的索引(index),並批量匯入一些文件: 建立索引: ``` PUT /bookdb_index { "settings": { "number_of_shards": 1 }} ``` 批量上傳文件: > 注意:現在7.x 已經啟用types 型別了,對應的操作語句也要修改下,`POST /bookdb_index/book/_bulk`換成`POST /bookdb_index/_bulk` ,然後進行操作。 ``` POST /bookdb_index/_bulk { "index": { "_id": 1 }} { "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" } { "index": { "_id": 2 }} { "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" } { "index": { "_id": 3 }} { "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" } { "index": { "_id": 4 }} { "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" } ``` ## 例子: ### 1. 基本的匹配(Query)查詢 有兩種方式來執行一個全文匹配查詢: - 使用 **Search Lite API**,它從 `url` 中讀取所有的查詢引數 - 使用完整 **JSON** 作為請求體,這樣你可以使用完整的 **Elasticsearch DSL** 下面是一個基本的匹配查詢,查詢任一欄位包含 Guide 的記錄 ``` GET /bookdb_index/_search?q=guide [Results] "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "1", "_score": 0.28168046, "_source": { "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": "manning" } }, { "_index": "bookdb_index", "_type": "book", "_id": "4", "_score": 0.24144039, "_source": { "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" } } ] ``` 下面是完整 Search Profiler版本的查詢,生成相同的內容: ``` { "query": { "multi_match" : { "query" : "guide", "fields" : [ "*" ] } } } ``` ![](https://raw.githubusercontent.com/PassZhang/passzhang.github.io/images-picgo/20200811160041.png) `multi_match` 是 `match` 的作為在多個欄位執行相同操作的一個速記法。`fields` 屬性用來指定查詢針對的欄位,`*`代表所有欄位,同時也可以使用單個欄位進行查詢,用逗號分隔開就可以。 在這個例子中,我們想要對文件的所有欄位進行匹配。兩個 **API** 都允許你指定要查詢的欄位。例如,查詢 `title` 欄位中包含 **in Action** 的書: ``` GET /bookdb_index/_search?q=title:in action [Results] "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "4", "_score": 0.6259885, "_source": { "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" } }, { "_index": "bookdb_index", "_type": "book", "_id": "3", "_score": 0.5975345, "_source": { "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" } } ] ``` 然而, 完整的 **DSL** 給予你靈活建立更復雜查詢和指定返回結果的能力(後面,我們會一一闡述)。在下面例子中,我們指定 `size` 限定返回的結果條數,from 指定起始位子,`_source` 指定要返回的欄位,以及語法高亮 ``` POST /bookdb_index/_search { "query": { "match" : { "title" : "in action" } }, "size": 2, "from": 0, "_source": [ "title", "summary", "publish_date" ], "highlight": { "fields" : { "title" : {} } } } [Results] "hits": { "total": 2, "max_score": 0.9105287, "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "3", "_score": 0.9105287, "_source": { "summary": "build scalable search applications using Elasticsearch without having to do complex low-level programming or understand advanced data science algorithms", "title": "Elasticsearch in Action", "publish_date": "2015-12-03" }, "highlight": { "title": [ "Elasticsearch in
Action" ] } }, { "_index": "bookdb_index", "_type": "book", "_id": "4", "_score": 0.9105287, "_source": { "summary": "Comprehensive guide to implementing a scalable search engine using Apache Solr", "title": "Solr in Action", "publish_date": "2014-04-05" }, "highlight": { "title": [ "Solr in
Action" ] } } ] } ``` 注意:對於多個詞查詢,`match` 允許指定是否使用 `and` 操作符來取代預設的 `or` 操作符。你還可以指定 `mininum_should_match` 選項來調整返回結果的相關程度。具體看後面的例子。 ### 2. 多欄位(Multi-filed)查詢 正如我們已經看到來的,為了根據多個欄位檢索(e.g. 在 `title` 和 `summary` 欄位都是相同的查詢字串的結果),你可以使用 `multi_match` 語句 ``` POST /bookdb_index/_search { "query": { "multi_match" : { "query" : "elasticsearch guide", "fields": ["title", "summary"] } } } [Results] "hits": { "total": 3, "max_score": 0.9448582, "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "1", "_score": 0.9448582, "_source": { "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": "manning" } }, { "_index": "bookdb_index", "_type": "book", "_id": "3", "_score": 0.17312013, "_source": { "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" } }, { "_index": "bookdb_index", "_type": "book", "_id": "4", "_score": 0.14965448, "_source": { "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" } } ] } ``` **注**:第三條被匹配,因為 `guide` 在 `summary` 欄位中被找到。 ### 3. Boosting 由於我們是多個欄位查詢,我們可能需要提高某一個欄位的分值。在下面的例子中,我們把 `summary` 欄位的分數提高三倍,為了提升 `summary` 欄位的重要度;因此,我們把文件 4 的相關度提高了。 ``` POST /bookdb_index/_search { "query": { "multi_match" : { "query" : "elasticsearch guide", "fields": ["title", "summary^3"] } }, "_source": ["title", "summary", "publish_date"] } [Results] "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "1", "_score": 0.31495273, "_source": { "summary": "A distibuted real-time search and analytics engine", "title": "Elasticsearch: The Definitive Guide", "publish_date": "2015-02-07" } }, { "_index": "bookdb_index", "_type": "book", "_id": "4", "_score": 0.14965448, "_source": { "summary": "Comprehensive guide to implementing a scalable search engine using Apache Solr", "title": "Solr in Action", "publish_date": "2014-04-05" } }, { "_index": "bookdb_index", "_type": "book", "_id": "3", "_score": 0.13094766, "_source": { "summary": "build scalable search applications using Elasticsearch without having to do complex low-level programming or understand advanced data science algorithms", "title": "Elasticsearch in Action", "publish_date": "2015-12-03" } } ] ``` **注**:提升不是簡簡單單通過提升因子把計算分數加成。實際的 `boost` 值通過歸一化和一些內部優化給出的。相關資訊請見 [Elasticsearch guide](https://www.elastic.co/guide/en/elasticsearch/guide/current/query-time-boosting.html) ### 4. Bool 組合查詢 為了提供更相關或者特定的結果,`AND`/`OR`/`NOT` 操作符可以用來調整我們的查詢。它是以 **布林查詢** 的方式來實現的。**布林查詢** 接受如下引數: - `must` 等同於 `AND` - `must_not` 等同於 `NOT` - `should` 等同於 `OR` >
上面的關鍵字中在一個query中只能出現一次 打比方,如果我想要查詢這樣型別的書:書名包含 **ElasticSearch** 或者(`OR`) **Solr**,並且(`AND`)它的作者是 **Clinton Gormley** 不是(`NOT`)**Radu Gheorge** ``` POST /bookdb_index/_search { "query": { "bool": { "must": { "match": { "authors": "clinton gormely" }}, "must_not": { "match": { "authors": "radu gheorge" }}, "should": [ { "match": { "title": "Elasticsearch" }}, { "match": { "title": "Solr" }} ] } } } 格式化版本: POST /bookdb_index/_search { "query": { "bool": { "must": { "match": { "authors": "clinton gormely" } }, "must_not": { "match": { "authors": "radu gheorge" } }, "should": [ { "match": { "title": "Elasticsearch" } }, { "match": { "title": "Solr" } } ] } } } [Results] "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "1", "_score": 0.3672021, "_source": { "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" } } ] ``` **注**:正如你所看到的,**布林查詢** 可以包裝任何其他查詢型別,包括其他布林查詢,以建立任意複雜或深度巢狀的查詢。 ### 5. 模糊(Fuzzy)查詢 在進行匹配和多項匹配時,可以啟用模糊匹配來捕捉拼寫錯誤,模糊度是基於原始單詞的編輯距離來指定的。 ``` POST /bookdb_index/_search { "query": { "multi_match" : { "query" : "comprihensiv guide", "fields": ["title", "summary"], "fuzziness": "AUTO" } }, "_source": ["title", "summary", "publish_date"], "size": 1 } [Results] "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "4", "_score": 0.5961596, "_source": { "summary": "Comprehensive guide to implementing a scalable search engine using Apache Solr", "title": "Solr in Action", "publish_date": "2014-04-05" } } ] ``` **注**:當術語長度大於 5 個字元時,`AUTO` 的模糊值等同於指定值 “2”。但是,80% 拼寫錯誤的編輯距離為 1,所以,將模糊值設定為 `1` 可能會提高您的整體搜尋效能。更多詳細資訊,請參閱**Elasticsearch指南中的“排版和拼寫錯誤”(Typos and Misspellings)**。 ### 6. 萬用字元(Wildcard)查詢 **萬用字元查詢** 允許你指定匹配的模式,而不是整個術語。 - `?` 匹配任何字元 - `*` 匹配零個或多個字元。 例如,要查詢名稱以字母’t’開頭的所有作者的記錄: ``` POST /bookdb_index/_search { "query": { "wildcard" : { "authors" : "t*" } }, "_source": ["title", "authors"], "highlight": { "fields" : { "authors" : {} } } } [Results] "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "1", "_score": 1, "_source": { "title": "Elasticsearch: The Definitive Guide", "authors": [ "clinton gormley", "zachary tong" ] }, "highlight": { "authors": [ "zachary tong" ] } }, { "_index": "bookdb_index", "_type": "book", "_id": "2", "_score": 1, "_source": { "title": "Taming Text: How to Find, Organize, and Manipulate It", "authors": [ "grant ingersoll", "thomas morton", "drew farris" ] }, "highlight": { "authors": [ "thomas morton" ] } }, { "_index": "bookdb_index", "_type": "book", "_id": "4", "_score": 1, "_source": { "title": "Solr in Action", "authors": [ "trey grainger", "timothy potter" ] }, "highlight": { "authors": [ "trey grainger", "timothy potter" ] } } ] ``` ### 7. 正則(Regexp)查詢 **正則查詢** 讓你可以使用比 **萬用字元查詢** 更復雜的模式進行查詢: ``` POST /bookdb_index/_search { "query": { "regexp" : { "authors" : "t[a-z]*y" } }, "_source": ["title", "authors"], "highlight": { "fields" : { "authors" : {} } } } [Results] "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "4", "_score": 1, "_source": { "title": "Solr in Action", "authors": [ "trey grainger", "timothy potter" ] }, "highlight": { "authors": [ "trey grainger", "timothy potter" ] } } ] ``` ### 8. 短語匹配(Match Phrase)查詢 **短語匹配查詢** 要求在請求字串中的所有查詢項必須都在文件中存在,文中順序也得和請求字串一致,且彼此相連。預設情況下,查詢項之間必須緊密相連,但可以設定 `slop` 值來指定查詢項之間可以分隔多遠的距離,結果仍將被當作一次成功的匹配。 ``` POST /bookdb_index/_search { "query": { "multi_match" : { "query": "search engine", "fields": ["title", "summary"], "type": "phrase", "slop": 3 } }, "_source": [ "title", "summary", "publish_date" ] } [Results] "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "4", "_score": 0.22327082, "_source": { "summary": "Comprehensive guide to implementing a scalable search engine using Apache Solr", "title": "Solr in Action", "publish_date": "2014-04-05" } }, { "_index": "bookdb_index", "_type": "book", "_id": "1", "_score": 0.16113183, "_source": { "summary": "A distibuted real-time search and analytics engine", "title": "Elasticsearch: The Definitive Guide", "publish_date": "2015-02-07" } } ] ``` **注**:在上述例子中,對於非整句型別的查詢,`_id` 為 1 的文件一般會比 `_id` 為 4 的文件得分高,結果位置也更靠前,因為它的欄位長度較短,但是對於 **短語匹配型別** 查詢,由於查詢項之間的接近程度是一個計算因素,因此 `_id` 為 4 的文件得分更高。 ### 9. 短語字首(Match Phrase Prefix)查詢 **短語字首式查詢** 能夠進行 **即時搜尋(search-as-you-type)** 型別的匹配,或者說提供一個查詢時的初級自動補全功能,無需以任何方式準備你的資料。和 `match_phrase` 查詢類似,它接收`slop` 引數(用來調整單詞順序和不太嚴格的相對位置)和 `max_expansions` 引數(用來限制查詢項的數量,降低對資源需求的強度)。 ``` POST /bookdb_index/_search { "query": { "match_phrase_prefix" : { "summary": { "query": "search en", "slop": 3, "max_expansions": 10 } } }, "_source": [ "title", "summary", "publish_date" ] } [Results] "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "4", "_score": 0.5161346, "_source": { "summary": "Comprehensive guide to implementing a scalable search engine using Apache Solr", "title": "Solr in Action", "publish_date": "2014-04-05" } }, { "_index": "bookdb_index", "_type": "book", "_id": "1", "_score": 0.37248808, "_source": { "summary": "A distibuted real-time search and analytics engine", "title": "Elasticsearch: The Definitive Guide", "publish_date": "2015-02-07" } } ] ``` **注**:採用 **查詢時即時搜尋** 具有較大的效能成本。更好的解決方案是採用 **索引時即時搜尋**。更多資訊,請檢視 **自動補齊介面(Completion Suggester API)** 或 **邊緣分詞器(Edge-Ngram filters)的用法**。 ### 10. 查詢字串(Query String) **查詢字串** 型別(**query_string**)的查詢提供了一個方法,用簡潔的簡寫語法來執行 **多匹配查詢**、 **布林查詢** 、 **提權查詢**、 **模糊查詢**、 **萬用字元查詢**、 **正則查詢** 和**範圍查詢**。下面的例子中,我們在那些作者是 **“grant ingersoll”** 或 **“tom morton”** 的某本書當中,使用查詢項 **“search algorithm”** 進行一次模糊查詢,搜尋全部欄位,但給 `summary` 的權重提升 2 倍。 ``` POST /bookdb_index/_search { "query": { "query_string": { "query": "(saerch~1 algorithm~1) AND (grant ingersoll) OR (tom morton)", "fields": [ "*", "summary^2" ] } }, "_source": [ "title", "summary", "authors" ], "highlight": { "fields": { "summary": {} } } } [Results] "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "2", "_score": 0.14558059, "_source": { "summary": "organize text using approaches such as full-text search, proper name recognition, clustering, tagging, information extraction, and summarization", "title": "Taming Text: How to Find, Organize, and Manipulate It", "authors": [ "grant ingersoll", "thomas morton", "drew farris" ] }, "highlight": { "summary": [ "organize text using approaches such as full-text search, proper name recognition, clustering, tagging, information extraction, and summarization" ] } } ] ``` ### 11. 簡單查詢字串(Simple Query String) **簡單請求字串** 型別(**simple_query_string**)的查詢是請求**字串型別**(**query_string**)查詢的一個版本,它更適合那種僅暴露給使用者一個簡單搜尋框的場景;因為它用 `+/\|/-` 分別替換了 `AND/OR/NOT`,並且自動丟棄了請求中無效的部分,不會在使用者出錯時,丟擲異常。 ``` POST /bookdb_index/_search { "query": { "simple_query_string" : { "query": "(saerch~1 algorithm~1) + (grant ingersoll) | (tom morton)", "fields": ["*", "summary^2"] } }, "_source": [ "title", "summary", "authors" ], "highlight": { "fields" : { "summary" : {} } } } [Results] "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 3.5710216, "hits" : [ { "_index" : "bookdb_index", "_type" : "book", "_id" : "2", "_score" : 3.5710216, "_source" : { "summary" : "organize text using approaches such as full-text search, proper name recognition, clustering, tagging, information extraction, and summarization", "title" : "Taming Text: How to Find, Organize, and Manipulate It", "authors" : [ "grant ingersoll", "thomas morton", "drew farris" ] }, "highlight" : { "summary" : [ "organize text using approaches such as full-text search, proper name recognition, clustering, tagging" ] } } ] } ``` ### 12. 詞條(Term)/多詞條(Terms)查詢 以上例子均為 `full-text`(全文檢索) 的示例。有時我們對結構化查詢更感興趣,希望得到更準確的匹配並返回結果,**詞條查詢** 和 **多詞條查詢** 可幫我們實現。在下面的例子中,我們要在索引中找到所有由 **Manning** 出版的圖書。 ``` POST /bookdb_index/_search { "query": { "term" : { "publisher": "manning" } }, "_source" : ["title","publish_date","publisher"] } [Results] "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "2", "_score": 1.2231436, "_source": { "publisher": "manning", "title": "Taming Text: How to Find, Organize, and Manipulate It", "publish_date": "2013-01-24" } }, { "_index": "bookdb_index", "_type": "book", "_id": "3", "_score": 1.2231436, "_source": { "publisher": "manning", "title": "Elasticsearch in Action", "publish_date": "2015-12-03" } }, { "_index": "bookdb_index", "_type": "book", "_id": "4", "_score": 1.2231436, "_source": { "publisher": "manning", "title": "Solr in Action", "publish_date": "2014-04-05" } } ] ``` 可使用詞條關鍵字來指定多個詞條,將搜尋項用陣列傳入。 ``` { "query": { "terms" : { "publisher": ["oreilly", "packt"] } } } ``` ### 13. 詞條(Term)查詢 - 排序(Sorted) **詞條查詢** 的結果(和其他查詢結果一樣)可以被輕易排序,多級排序也被允許: ``` POST /bookdb_index/_search { "query": { "term": { "publisher": "manning" } }, "_source": [ "publish_date", "publisher" ], "sort": [ { "publish_date": { "order": "desc" } } ] } [Results] "hits" : { "total" : { "value" : 3, "relation" : "eq" }, "max_score" : null, "hits" : [ { "_index" : "bookdb_index", "_type" : "book", "_id" : "3", "_score" : null, "_source" : { "publisher" : "manning", "publish_date" : "2015-12-03" }, "sort" : [ 1449100800000 ] }, { "_index" : "bookdb_index", "_type" : "book", "_id" : "4", "_score" : null, "_source" : { "publisher" : "manning", "publish_date" : "2014-04-05" }, "sort" : [ 1396656000000 ] }, { "_index" : "bookdb_index", "_type" : "book", "_id" : "2", "_score" : null, "_source" : { "publisher" : "manning", "publish_date" : "2013-01-24" }, "sort" : [ 1358985600000 ] } ] } ``` ### 14. 範圍查詢 另一個結構化查詢的例子是 **範圍查詢**。在這個例子中,我們要查詢 2015 年出版的書。 ``` POST /bookdb_index/_search { "query": { "range": { "publish_date": { "gte": "2015-01-01", "lte": "2015-12-31" } } }, "_source": [ "title", "publish_date", "publisher" ] } [Results] "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "1", "_score": 1, "_source": { "publisher": "oreilly", "title": "Elasticsearch: The Definitive Guide", "publish_date": "2015-02-07" } }, { "_index": "bookdb_index", "_type": "book", "_id": "3", "_score": 1, "_source": { "publisher": "manning", "title": "Elasticsearch in Action", "publish_date": "2015-12-03" } } ] ``` **注**:**範圍查詢** 用於日期、數字和字串型別的欄位。 ### 15. 過濾(Filtered)查詢 過濾查詢允許你可以過濾查詢結果。對於我們的例子中,要在標題或摘要中檢索一些書,查詢項為 **Elasticsearch**,但我們又想篩出那些僅有 20 個以上評論的。 > 新版本不支援filtered 查詢,已經棄用這個關鍵字 ``` POST /bookdb_index/_search { "query": { "filtered": { "query" : { "multi_match": { "query": "elasticsearch", "fields": ["title","summary"] } }, "filter": { "range" : { "num_reviews": { "gte": 20 } } } } }, "_source" : ["title","summary","publisher", "num_reviews"] } [Results] "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "1", "_score": 0.5955761, "_source": { "summary": "A distibuted real-time search and analytics engine", "publisher": "oreilly", "num_reviews": 20, "title": "Elasticsearch: The Definitive Guide" } } ] ``` **注**:**過濾查詢** 並不強制它作用於其上的查詢必須存在。如果未指定查詢,`match_all` 基本上會返回索引內的全部文件。實際上,過濾只在第一次執行,以減少所需的查詢面積,並且,在第一次使用後過濾會被快取,大大提高了效能。 **更新**:**過濾查詢** 將在 `ElasticSearch 5` 中移除,使用 **布林查詢** 替代。 下面有個例子使用 **布林查詢** 重寫上面的例子: ``` POST /bookdb_index/_search { "query": { "bool": { "must" : { "multi_match": { "query": "elasticsearch", "fields": ["title","summary"] } }, "filter": { "range" : { "num_reviews": { "gte": 20 } } } } }, "_source" : ["title","summary","publisher", "num_reviews"] } ``` 在後續的例子中,我們將會把它使用在 **多重過濾** 中。 ### 16. 多重過濾(Multiple Filters) **多重過濾** 可以結合 **布林查詢** 使用,下一個例子中,過濾查詢決定只返回那些包含至少20條評論,且必須在 2015 年前出版,且由 O’Reilly 出版的結果。 ``` POST /bookdb_index/_search { "query": { "bool": { "must": [ { "match": { "title": "Elasticsearch" } } ], "filter": [ { "term": { "publisher": "oreilly" } }, { "range": { "publish_date": { "gte": "2014-12-31" } } } ] } }, "_source": [ "title", "publisher", "publish_date" ] } [Results] "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "1", "_score": 0.5955761, "_source": { "summary": "A distibuted real-time search and analytics engine", "publisher": "oreilly", "num_reviews": 20, "title": "Elasticsearch: The Definitive Guide", "publish_date": "2015-02-07" } } ] ``` ### 17. 作用分值: 域值(Field Value)因子 也許在某種情況下,你想把文件中的某個特定域作為計算相關性分值的一個因素,比較典型的場景是你想根據普及程度來提高一個文件的相關性。在我們的示例中,我們想把最受歡迎的書(基於評論數判斷)的權重進行提高,可使用 `field_value_factor` 用以影響分值。 ``` POST /bookdb_index/_search { "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"] } [Results] "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "1", "_score": 0.44831306, "_source": { "summary": "A distibuted real-time search and analytics engine", "num_reviews": 20, "title": "Elasticsearch: The Definitive Guide", "publish_date": "2015-02-07" } }, { "_index": "bookdb_index", "_type": "book", "_id": "4", "_score": 0.3718407, "_source": { "summary": "Comprehensive guide to implementing a scalable search engine using Apache Solr", "num_reviews": 23, "title": "Solr in Action", "publish_date": "2014-04-05" } }, { "_index": "bookdb_index", "_type": "book", "_id": "3", "_score": 0.046479136, "_source": { "summary": "build scalable search applications using Elasticsearch without having to do complex low-level programming or understand advanced data science algorithms", "num_reviews": 18, "title": "Elasticsearch in Action", "publish_date": "2015-12-03" } }, { "_index": "bookdb_index", "_type": "book", "_id": "2", "_score": 0.041432835, "_source": { "summary": "organize text using approaches such as full-text search, proper name recognition, clustering, tagging, information extraction, and summarization", "num_reviews": 12, "title": "Taming Text: How to Find, Organize, and Manipulate It", "publish_date": "2013-01-24" } } ] ``` **注1**: 我們可能剛運行了一個常規的 `multi_match` (多匹配)查詢,並對 `num_reviews` 域進行了排序,這讓我們失去了評估相關性分值的好處。 **注2**: 有大量的附加引數可用來調整提升原始相關性分值效果的程度,比如 `modifier`, `factor`, `boost_mode` 等等,至於細節可在 **Elasticsearch** 指南中探索。 ### 18. 作用分值: 衰變(Decay)函式 假設不想使用域值做遞增提升,而你有一個理想目標值,並希望用這個加權因子來對這個離你較遠的目標值進行衰減。有個典型的用途是基於經緯度、價格或日期等數值域的提升。在如下的例子中,我們查詢在2014年6月左右出版的,查詢項是 **search engines** 的書。 ``` POST /bookdb_index/_search { "query": { "function_score": { "query": { "multi_match" : { "query" : "search engine", "fields": ["title", "summary"] } }, "functions": [ { "exp": { "publish_date" : { "origin": "2014-06-15", "offset": "7d", "scale" : "30d" } } } ], "boost_mode" : "replace" } }, "_source": ["title", "summary", "publish_date", "num_reviews"] } [Results] "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "4", "_score": 0.27420625, "_source": { "summary": "Comprehensive guide to implementing a scalable search engine using Apache Solr", "num_reviews": 23, "title": "Solr in Action", "publish_date": "2014-04-05" } }, { "_index": "bookdb_index", "_type": "book", "_id": "1", "_score": 0.005920768, "_source": { "summary": "A distibuted real-time search and analytics engine", "num_reviews": 20, "title": "Elasticsearch: The Definitive Guide", "publish_date": "2015-02-07" } }, { "_index": "bookdb_index", "_type": "book", "_id": "2", "_score": 0.000011564, "_source": { "summary": "organize text using approaches such as full-text search, proper name recognition, clustering, tagging, information extraction, and summarization", "num_reviews": 12, "title": "Taming Text: How to Find, Organize, and Manipulate It", "publish_date": "2013-01-24" } }, { "_index": "bookdb_index", "_type": "book", "_id": "3", "_score": 0.0000059171475, "_source": { "summary": "build scalable search applications using Elasticsearch without having to do complex low-level programming or understand advanced data science algorithms", "num_reviews": 18, "title": "Elasticsearch in Action", "publish_date": "2015-12-03" } } ] ``` ### 19. 函式分值: 指令碼評分 當內建的評分函式無法滿足你的需求時,還可以用 **Groovy** 指令碼。在我們的例子中,想要指定一個指令碼,能在決定把 `num_reviews` 的因子計算多少之前,先將 `publish_date` 考慮在內。因為很新的書也許不會有評論,分值不應該被懲罰。 評分指令碼如下: ``` publish_date = doc['publish_date'].value num_reviews = doc['num_reviews'].value if (publish_date > Date.parse('yyyy-MM-dd', threshold).getTime()) { my_score = Math.log(2.5 + num_reviews) } else { my_score = Math.log(1 + num_reviews) } return my_score ``` 在 `script_score` 引數內動態呼叫評分指令碼: ``` POST /bookdb_index/book/_search { "query": { "function_score": { "query": { "multi_match" : { "query" : "search engine", "fields": ["title", "summary"] } }, "functions": [ { "script_score": { "params" : { "threshold": "2015-07-30" }, "script": "publish_date = doc['publish_date'].value; num_reviews = doc['num_reviews'].value; if (publish_date > Date.parse('yyyy-MM-dd', threshold).getTime()) { return log(2.5 + num_reviews) }; return log(1 + num_reviews);" } } ] } }, "_source": ["title", "summary", "publish_date", "num_reviews"] } [Results] "hits": { "total": 4, "max_score": 0.8463001, "hits": [ { "_index": "bookdb_index", "_type": "book", "_id": "1", "_score": 0.8463001, "_source": { "summary": "A distibuted real-time search and analytics engine", "num_reviews": 20, "title": "Elasticsearch: The Definitive Guide", "publish_date": "2015-02-07" } }, { "_index": "bookdb_index", "_type": "book", "_id": "4", "_score": 0.7067348, "_source": { "summary": "Comprehensive guide to implementing a scalable search engine using Apache Solr", "num_reviews": 23, "title": "Solr in Action", "publish_date": "2014-04-05" } }, { "_index": "bookdb_index", "_type": "book", "_id": "3", "_score": 0.08952084, "_source": { "summary": "build scalable search applications using Elasticsearch without having to do complex low-level programming or understand advanced data science algorithms", "num_reviews": 18, "title": "Elasticsearch in Action", "publish_date": "2015-12-03" } }, { "_index": "bookdb_index", "_type": "book", "_id": "2", "_score": 0.07602123, "_source": { "summary": "organize text using approaches such as full-text search, proper name recognition, clustering, tagging, information extraction, and summarization", "num_reviews": 12, "title": "Taming Text: How to Find, Organize, and Manipulate It", "publish_date": "2013-01-24" } } ] } ``` **注1**: 要在 **Elasticsearch** 例項中使用動態指令碼,必須在 *config/elasticsearch.yaml* 檔案中啟用它;也可以使用儲存在 **Elasticsearch** 伺服器上的指令碼。建議看看 **Elasticsearch** 指南文件獲取更多資訊。 **注2**: 因 **JSON** 不能包含嵌入式換行符,請使用分號來分割語句。 > 引用自:[23 USEFUL ELASTICSEARCH EXAMPLE QUERIES](http://distributedbytes.timojo.com/2016/07/23-useful-elasticsearch-example-queri