昨天我們在本地啟動了 Elasticsearch,建立固定 mapping 並插入測試資料。今天的目標是:
理解並操作 match 查詢,學會用 bool 組合條件,用 terms 進行過濾(filter)
match 是最常用的全文檢索:
curl -X POST "http://localhost:9200/books/_search?pretty" \
-H 'Content-Type: application/json' \
-d '{
"query": {
"match": { "title": "golang" }
}
}'
這會透過 analyzer(分詞器)來搜尋 title,所以即使我們存的是 "Golang 101",用小寫 "golang" 也能匹配。
如果改成搜尋 "elasticsearch",就能找到 "Elasticsearch入門"。
實際應用裡,我們常需要多條件組合,這時就用 bool:
curl -X POST "http://localhost:9200/books/_search?pretty" \
-H 'Content-Type: application/json' \
-d '{
"query": {
"bool": {
"must": [
{ "match": { "title": "golang" } }
],
"filter": [
{ "term": { "tags": "programming" } }
]
}
}
}'
這表示:
must:title 必須包含 "golang"
filter:tags 必須是 "programming"
must 會影響相關性(score),filter 不會,但能加快查詢速度。
如果我們想要「一次比對多個值」,可以用 terms:
curl -X POST "http://localhost:9200/books/_search?pretty" \
-H 'Content-Type: application/json' \
-d '{
"query": {
"terms": {
"tags": ["golang", "search"]
}
}
}'
這會回傳所有 tags 屬於 "golang" 或 "search" 的文件。
注意:terms 適用於 keyword 欄位,如果用在 text 會失敗,因為 text 會被分詞。
我們可以在 ESSearchService 裡,加入不同查詢模式。例如:
func (es *ESSearchService) SearchByTag(ctx context.Context, tag string) ([]SearchResult, error) {
body := fmt.Sprintf(`{
"query": {
"term": { "tags": "%s" }
}
}`, tag)
return es.searchRaw(ctx, body)
}
或是寫一個支援 bool 的版本,讓 /search API 能支援多條件。
今天我們完成了:
match 查詢(全文檢索)bool 組合 must + filter
terms 一次比對多個 keyword到這裡,我們的 /search API 已經能支援更靈活的檢索。
明天,我們會處理 分頁,並從 from/size 進階到 search_after,避免深度分頁效能問題。