作者:來自 Elastic?Justin Castilla
想要獲得 Elastic 認證?看看下一次 Elasticsearch Engineer 培訓什么時候開始吧!
Elasticsearch 擁有大量新功能,可以幫助你為你的使用場景構建最佳的搜索解決方案。深入了解我們的示例 notebooks,開始免費 cloud 試用,或立即在本地機器上體驗 Elastic。
在 Elasticsearch 中,在字段中搜索包含特定子字符串的文檔是一項常見需求。本文將探討在 Elasticsearch 中進行查詢的高級技巧,以找到字段中包含特定子字符串的文檔。我們將討論 query_string、match_phrase 和 wildcard 查詢的使用,使用分析器和分詞器來提高搜索準確性,以及可用于定位字段中子字符串的 ES|QL 函數。如果你想了解精確值與全文本的使用差異,請查看本指南。
1)query_string 查詢
query_string 查詢是一種強大且靈活的方式,用于搜索包含特定子字符串的文檔。它允許你使用 Lucene 查詢語法,提供了多種搜索選項。以下是一個 query_string 查詢的示例,用于搜索包含子字符串 “example” 的文檔:
GET /_search
{"query": {"query_string": {"query": "*example*"}}
}
在這個示例中,星號( * )被用作通配符,匹配任意字符序列。query_string 查詢會返回在任意字段中包含子字符串 “example” 的文檔。但需要注意的是,前綴通配符可能會對你的集群性能產生負面影響。
2)match_phrase 查詢
match_phrase 查詢是另一種搜索包含特定子字符串文檔的方式。它會在字段中搜索精確短語,并且可以配合 slop 參數使用,以允許單詞順序的變化。以下是一個 match_phrase 查詢的示例,用于搜索包含子字符串 “quick brown” 的文檔:
GET /_search
{"query": {"match_phrase": {"field_name": "quick brown"}}
}
在這個示例中,match_phrase 查詢會返回在指定字段中包含確切短語 “quick brown” 的文檔。
3)wildcard 查詢
wildcard 查詢是一種簡單的方式,用于搜索包含特定子字符串的文檔。它使用通配符來匹配字段中任意字符序列。以下是一個 wildcard 查詢的示例,用于搜索包含子字符串 “exam” 的文檔:
GET /_search
{"query": {"wildcard": {"field_name": "*exam*"}}
}
在這個示例中,wildcard 查詢會返回在指定字段中包含子字符串 “exam” 的文檔。在這種情況下,也需要特別注意在 wildcard 查詢中使用前綴通配符,因為這可能會降低搜索性能。
4)分析器和分詞器
為了提高子字符串搜索的準確性,你可以使用分析器和分詞器來處理文檔中的文本。分析器負責將文本分解成 token,這些 token 會用于索引和搜索。分詞器是分析器的一個組件,用于將文本拆分為單個 token。
例如,你可以使用 n-gram 分詞器從輸入文本中創建不同長度的 token。這樣可以通過匹配不同長度的子字符串來提高子字符串搜索的準確性。以下是一個使用 n-gram 分詞器創建自定義分析器的示例:
PUT /my_index
{"settings": {"analysis": {"analyzer": {"my_analyzer": {"tokenizer": "my_tokenizer"}},"tokenizer": {"my_tokenizer": {"type": "ngram","min_gram": 3,"max_gram": 5}}}}
}
在這個示例中,自定義分析器使用了一個 n-gram 分詞器,其最小 token 長度為 3,最大 token 長度為 5。你可以在索引文檔時以及進行子字符串搜索時使用這個自定義分析器。
需要注意的是,將大量文本分詞為 n?gram 會顯著增加倒排索引中的 term 數量,從而不必要地增加存儲,并降低索引和查詢的速度。最好只對需要子字符串匹配的文本字段使用 n?gram 分詞器。
5)ES|QL 函數
LOCATE
ES|QL 的 LOCATE 函數用于查找文檔中指定子字符串的首次出現位置。LOCATE 函數的調用方式如下:
這里,string 是要查詢的字段,substring 是目標子字符串,start 是字符串中的整數偏移量。這個函數會返回從提供的 start 位置之后首次出現子字符串的位置的整數值;如果子字符串不存在,則返回 0。
對于字段中出現多次的子字符串,不建議使用這個函數,因為 ES|QL 中不支持迭代處理,它是一種純聲明式、流水線風格的查詢語言。
MATCH
MATCH 函數會返回布爾值 true,如果傳入 query 參數的子字符串出現在傳入 field 參數的文本中。它適用于一般的全文搜索,相關性由術語是否存在決定,而不考慮它們的位置。
可選的命名函數參數可以傳入以獲得更細粒度的控制,比如模糊度( fuzziness )、用于解釋文本的操作符,以及寬容度( leniency )值。
注意,查詢中可以包含多個詞項,結果可能包含這些詞項中的任意一個,但不一定按給定順序出現。
示例:搜索 “quick brown fox” 會匹配包含 “the fox is quick and brown” 的文檔。
MATCH_PHRASE
MATCH_PHRASE 與 MATCH 函數類似,但它必須匹配傳入函數的整個短語,而不是單個詞項。它適用于你想搜索確切短語而不僅僅是單個詞項是否存在的情況。
MATCH_PHRASE 也有可選的命名參數,允許各種細化設置,比如 slop 和 token 分析器。
示例:搜索 “quick brown fox” 只會匹配包含確切短語 “quick brown fox” 的文檔。
KQL
KQL 查詢指的是用 Kibana Query Language(KQL)編寫的查詢。KQL 是 Kibana 中使用的搜索和過濾語言,Kibana 是我們的數據可視化工具。Elastic 已將這種查詢語言引入 ES|QL,以增強搜索功能。
示例:搜索 “foo: bar” AND “baz > 12” 會返回所有 “foo” 字段包含 “bar” 且 “baz” 字段值大于 12 的文檔。
QSTR
QSTR 是 Lucene 使用的一種查詢格式,提供對文本字段的靈活、基于相關性的搜索,類似于在 Elasticsearch DSL 中使用 match 查詢。
示例:在工單索引中使用 QSTR 搜索 "timeout error OR "connection refused"",會返回包含 “timeout error” 或確切短語 “connection refused” 的工單文檔。
QSTR 還提供最多的選項,能夠在搜索中提供高度的粒度和靈活性。
附加內容:區間查詢和跨度查詢
區間查詢 - interval queries
區間查詢是搜索必須按照給定順序出現的詞項的查詢。以下是一個示例查詢:
POST _search
{"query": {"intervals" : {"my_text" : {"all_of" : {"ordered" : true,"intervals" : [{"match" : {"query" : "it's rainy outside","max_gaps" : 0,"ordered" : true}},{"any_of" : {"intervals" : [{ "match" : { "query" : "curl up with a good book" } },{ "match" : { "query" : "listen to a podcast" } }]}}]}}}}
}
該查詢搜索短語 “it’s rainy outside”,后面緊跟著 “curl up with a good book” 或 “listen to a podcast” 中的任意一個詞項。
這句話會匹配:“When it’s rainy outside, I like to dress up in cozy clothes, turn on some classical music, and curl up with a good book.”
這句話不會匹配:“I find it best to listen to a podcast in my car when there’s a lot of traffic and it’s rainy outside.”
這是因為 “all_of”: {“ordered”: true} 條款,要求上述順序必須嚴格遵守。
這是一個非常強大且可擴展的查詢,適合用于動態且復雜的子字符串搜索。
跨度查詢 - span
跨度查詢通過操作 token 偏移量而非原始文本,提供了一種低級且帶位置感知的子字符串搜索方法。跨度可以嵌套子跨度,這些子跨度必須滿足諸如在指定距離內出現在另一個跨度之前或之后等約束條件。這使得它們非常適合處理某些領域(如法律文件),在這些領域中常見術語在靠近特定關鍵詞時會獲得特殊含義。
GET /_search
{"query": {"span_near": {"clauses": [{ "span_term": { "field": "contract" } },{ "span_term": { "field": "breach" } }],"slop": 3,"in_order": false}}
}
例如,你可以使用 span_near 查詢來查找距離 “breach” 四個 token 以內的 “contract”。一份冗長的法律摘要中可能多次提到 “contract”,但只有兩個地方出現了短語 “breach of obligation and contract” 或 “breach of contract litigation”。通過調整跨度距離(例如 slop: 3),你只會匹配這兩個上下文,忽略所有其他的 “contract” 出現。
總結
Elasticsearch 提供了多種高級技術,用于查詢包含特定子字符串的文檔。通過使用 query_string、match_phrase 和 wildcard 查詢,自定義分析器和分詞器,ES|QL 函數,甚至是區間查詢或跨度查詢,你可以提高子字符串搜索的準確性和靈活性。嘗試這些技術,找到最適合你具體用例和數據集的方法。
原文:https://www.elastic.co/search-labs/blog/elasticsearch-string-contains-substring