大家好,我是 V 哥。Elasticsearch 是一個強大的全文搜索和分析引擎,廣泛應(yīng)用于各種場景。以下是五個常見業(yè)務(wù)場景中的 Elasticsearch 實戰(zhàn)應(yīng)用案例及其詳細分析。
業(yè)務(wù)場景: 某電商平臺需要為用戶提供高效的商品搜索功能,要求在海量數(shù)據(jù)中快速返回匹配結(jié)果,并高亮顯示關(guān)鍵字,提升用戶體驗。
解決方案:
match
查詢類型,配合 multi_match
進行多個字段的搜索,確保用戶查詢能匹配到商品名稱、描述等相關(guān)字段。highlight
功能,在返回的結(jié)果中對匹配的關(guān)鍵字進行高亮處理,提升用戶可讀性。詳細分析: Elasticsearch 提供了強大的倒排索引機制,使得全文搜索非常高效。通過靈活的查詢組合,用戶可以精確匹配多種字段的搜索條件,同時高亮功能可以讓用戶直觀地看到匹配位置。此方案提升了用戶的搜索體驗,并能迅速處理電商平臺的大量商品數(shù)據(jù)。
要實現(xiàn)全文搜索與高亮顯示的功能,主要分為以下幾個步驟,包括 Elasticsearch 環(huán)境的設(shè)置、數(shù)據(jù)的索引、查詢的編寫,以及高亮顯示的處理。具體如下:
確保 Elasticsearch 已經(jīng)安裝并運行。如果尚未安裝,可以通過 Docker 快速啟動一個 Elasticsearch 實例:
docker run -d --name elasticsearch -p 9200:9200 -e "discovery.type=single-node" elasticsearch:8.0.0
然后可以通過以下 URL 訪問 Elasticsearch API:
http://localhost:9200
在實際場景中,可能需要為商品(或者其他實體)創(chuàng)建一個索引。首先為該索引配置字段和分詞器,確保字段能夠支持全文檢索。
我們?yōu)樯唐沸畔?chuàng)建一個索引,定義商品名稱和描述的字段類型為 text
,并指定使用默認的分詞器。
PUT /products
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"description": {
"type": "text"
},
"price": {
"type": "float"
}
}
}
}
在創(chuàng)建好索引后,可以開始向索引中插入一些商品數(shù)據(jù)。以下是一些商品的示例數(shù)據(jù):
POST /products/_doc/1
{
"name": "huawei mate 70",
"description": "mate 70 手機是搭載純血鴻蒙NEXT 系統(tǒng)的第一款旗艦機",
"price": 6500
}
POST /products/_doc/2
{
"name": "huawei Mate XT非凡大師",
"description": "非凡大師 16GB+1TB玄黑 ULTIMATE DESIGN",
"price": 23999
}
POST /products/_doc/3
{
"name": "huawei Mate X5",
"description": "huawei mate x5 12GB+512GB 羽砂黑 超輕薄四曲折疊,超高清高分辨率臨境雙屏,超智慧靈犀通信",
"price": 12499
}
使用 match
查詢來實現(xiàn)對商品名稱和描述字段的全文搜索。為了能高效地搜索到多個字段中的內(nèi)容,我們可以使用 multi_match
查詢。比如用戶在搜索框中輸入了“iPhone”時,我們希望在商品名稱和描述中都查找匹配項。
GET /products/_search
{
"query": {
"multi_match": {
"query": "X5",
"fields": ["name", "description"]
}
}
}
這個查詢會返回所有匹配“iPhone”關(guān)鍵字的商品。
為了增強用戶體驗,可以使用 Elasticsearch 的高亮功能,顯示搜索結(jié)果中的匹配詞語。通過在查詢中添加 highlight
,我們可以讓關(guān)鍵字在返回結(jié)果中高亮顯示。
GET /products/_search
{
"query": {
"multi_match": {
"query": "X5",
"fields": ["name", "description"]
}
},
"highlight": {
"fields": {
"name": {},
"description": {}
}
}
}
Elasticsearch 返回的結(jié)果中會包含高亮字段。例如,假設(shè)用戶搜索“iPhone”,以下是一個可能的響應(yīng)結(jié)果:
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"hits": [
{
"_index": "products",
"_id": "1",
"_source": {
"name": "huawei Mate X5",
"description": "huawei mate x5 12GB+512GB 羽砂黑 超輕薄四曲折疊,超高清高分辨率臨境雙屏,超智慧靈犀通信",
"price": 12499
},
"highlight": {
"name": ["huawei <em>x5</em> 14"],
"description": ["huawei mate <em>x5</em> 12GB+512GB 羽砂黑 超輕薄四曲折疊,超高清高分辨率臨境雙屏,超智慧靈犀通信"]
}
}
]
}
}
從結(jié)果中可以看到,高亮部分會以 <em>
標簽包裹,我們可以根據(jù)需求在前端使用 CSS 或 HTML 標簽來調(diào)整高亮顯示的樣式。
在前端頁面中,搜索結(jié)果可以通過解析響應(yīng)中的 _source
和 highlight
字段,將高亮部分以更明顯的方式展示給用戶。假設(shè)我們使用 JavaScript 進行結(jié)果展示,代碼可能如下:
<ul id="search-results"></ul>
<script>
const results = [
{
"_source": {
"name": "huawei Mate X5",
"description": "huawei mate x5 12GB+512GB 羽砂黑 超輕薄四曲折疊,超高清高分辨率臨境雙屏,超智慧靈犀通信"
},
"highlight": {
"name": ["huawei Mate <em>X5</em>"],
"description": ["huawei mate <em>X5</em> 12GB+512GB 羽砂黑 超輕薄四曲折疊,超高清高分辨率臨境雙屏,超智慧靈犀通信"]
}
}
];
const resultsContainer = document.getElementById('search-results');
results.forEach(result => {
const listItem = document.createElement('li');
listItem.innerHTML = `
<h2>${result.highlight.name ? result.highlight.name[0] : result._source.name}</h2>
<p>${result.highlight.description ? result.highlight.description[0] : result._source.description}</p>
`;
resultsContainer.appendChild(listItem);
});
</script>
在上面的例子中,前端會展示包含 <em>
標簽的文本,該標簽會將搜索到的關(guān)鍵字(如“x5”)高亮顯示。
如果搜索場景中需要更復(fù)雜的匹配,比如同義詞搜索、拼寫糾錯等,可以進一步定制分詞器或通過同義詞字典進行擴展。
PUT /products
{
"settings": {
"analysis": {
"analyzer": {
"synonym_analyzer": {
"tokenizer": "whitespace",
"filter": ["synonym_filter"]
}
},
"filter": {
"synonym_filter": {
"type": "synonym",
"synonyms": [
"x5, mate x5",
"mate70, 非凡大師"
]
}
}
}
},
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "synonym_analyzer"
},
"description": {
"type": "text",
"analyzer": "synonym_analyzer"
}
}
}
}
通過同義詞分析器,用戶搜索“ huawei mate”時也可以匹配到包含“mate”的文檔,從而進一步提升搜索的準確性。
通過上述步驟,我們可以實現(xiàn)一個完整的 Elasticsearch 全文搜索與高亮顯示的功能。這個功能適用于電商平臺、博客搜索、文檔系統(tǒng)等多種業(yè)務(wù)場景,提供快速、高效、用戶友好的搜索體驗。
業(yè)務(wù)場景: 某 SaaS 公司需要對其分布式系統(tǒng)中的應(yīng)用日志進行集中管理、實時監(jiān)控與分析,要求快速定位系統(tǒng)錯誤和性能瓶頸。使用 Elasticsearch 可以集中存儲和分析分布式系統(tǒng)中的日志,快速查詢和監(jiān)控日志數(shù)據(jù)。
解決方案:
aggregations
聚合功能進行日志的統(tǒng)計分析,如錯誤分類、按時間段的訪問量統(tǒng)計等。詳細分析: Elasticsearch 是 ELK(Elasticsearch, Logstash, Kibana)技術(shù)棧中的核心組件,它不僅支持大規(guī)模日志數(shù)據(jù)的存儲,還能通過內(nèi)置的聚合和搜索功能,實現(xiàn)實時分析與可視化。對于分布式系統(tǒng)中的日志分析場景,Elasticsearch 通過分片和復(fù)制機制提供了高可用性和擴展性,保證了海量日志數(shù)據(jù)的快速查詢和處理。
以下是一個完整的實現(xiàn)案例,包括從日志的收集、傳輸、存儲到實時分析的步驟。
在實際應(yīng)用中,日志的收集與分析一般采用 ELK(Elasticsearch, Logstash, Kibana)或 EFK(Elasticsearch, Filebeat, Kibana)技術(shù)棧。這里我們選擇 Filebeat
作為日志采集工具,Elasticsearch
作為數(shù)據(jù)存儲和查詢引擎,Kibana
作為可視化和監(jiān)控工具。
## 啟動 Elasticsearch
docker run -d --name elasticsearch -p 9200:9200 -e "discovery.type=single-node" elasticsearch:8.0.0
## 啟動 Kibana
docker run -d --name kibana -p 5601:5601 --link elasticsearch:elasticsearch kibana:8.0.0
訪問 Kibana: http://localhost:5601
,確保 Elasticsearch 和 Kibana 正常啟動并連接成功。
Filebeat
是一個輕量級的日志收集工具,能夠監(jiān)控文件變化,并將日志數(shù)據(jù)發(fā)送到 Elasticsearch 或 Logstash。
可以通過以下方式在系統(tǒng)中安裝 Filebeat:
## 在 Linux 中安裝 Filebeat
sudo apt-get install filebeat
Filebeat 的配置文件 filebeat.yml
是日志收集的核心,它定義了從哪里收集日志,日志如何處理,并發(fā)送到哪里。以下是一個典型的配置文件,用于將日志發(fā)送到 Elasticsearch。
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/myapp/*.log # 日志文件路徑
output.elasticsearch:
hosts: ["localhost:9200"] # 指定 Elasticsearch 地址
username: "elastic"
password: "changeme" # 設(shè)置 Elasticsearch 認證
setup.kibana:
host: "localhost:5601" # Kibana 的地址
這段配置定義了 Filebeat 從 /var/log/myapp/*.log
目錄下讀取日志文件,并將其傳送到 Elasticsearch 中進行存儲。同時,還配置了 Kibana 的連接,便于后續(xù)可視化分析。
sudo filebeat modules enable system
sudo filebeat setup
sudo service filebeat start
在日志數(shù)據(jù)發(fā)送到 Elasticsearch 之前,需要為日志數(shù)據(jù)創(chuàng)建索引,并為其指定字段映射。可以使用 Elasticsearch 動態(tài)映射的功能來自動創(chuàng)建索引,但為了更好地處理日志中的日期、字符串等數(shù)據(jù)類型,建議手動創(chuàng)建索引映射。
PUT /logs-system
{
"mappings": {
"properties": {
"timestamp": {
"type": "date"
},
"log.level": {
"type": "keyword"
},
"message": {
"type": "text"
},
"service.name": {
"type": "keyword"
},
"host.name": {
"type": "keyword"
},
"process.pid": {
"type": "integer"
}
}
}
}
在這個映射中,我們?yōu)橄到y(tǒng)日志定義了幾個重要的字段:
timestamp
: 日志的時間戳,數(shù)據(jù)類型為 date
。log.level
: 日志級別,如 INFO
, ERROR
等,數(shù)據(jù)類型為 keyword
。message
: 日志的內(nèi)容,使用 text
類型進行全文索引。service.name
: 服務(wù)名稱,用于區(qū)分不同的服務(wù)。host.name
: 記錄日志的主機名,用于定位具體的機器。process.pid
: 進程 ID,用于進一步跟蹤問題。
當(dāng) Filebeat 啟動后,它會監(jiān)控配置文件中的日志文件路徑(例如 /var/log/myapp/*.log
),并將新生成的日志行發(fā)送到 Elasticsearch 中。
假設(shè)應(yīng)用程序生成了如下格式的日志文件 /var/log/myapp/app.log
:
2024-10-14T12:30:00Z INFO [my-service] Service started
2024-10-14T12:31:00Z ERROR [my-service] Failed to connect to database
2024-10-14T12:32:00Z WARN [my-service] Low disk space on /dev/sda1
這些日志文件會被 Filebeat 采集并自動傳送到 Elasticsearch 中,按配置的索引存儲。
一旦日志數(shù)據(jù)進入 Elasticsearch,我們可以使用 Kibana 進行實時查詢和分析。
http://localhost:5601
。Management
> Index Patterns
,創(chuàng)建一個新的索引模式 logs-system-*
,這將匹配 Elasticsearch 中的日志索引。timestamp
字段設(shè)置為時間過濾字段,用于時間范圍篩選。Kibana 提供了一個非常強大的查詢語言——KQL(Kibana Query Language),可以在 Kibana 中對日志數(shù)據(jù)進行各種查詢和過濾。例如:
log.level: "ERROR"
service.name: "my-service"
log.level: "ERROR" AND @timestamp > "2024-10-14T12:00:00Z"
Elasticsearch 提供了強大的 aggregations
聚合功能,可以用于統(tǒng)計和分析日志數(shù)據(jù)中的各種模式。以下是幾個常用的聚合查詢示例:
GET /logs-system/_search
{
"size": 0,
"aggs": {
"by_log_level": {
"terms": {
"field": "log.level"
}
}
}
}
GET /logs-system/_search
{
"size": 0,
"query": {
"match": {
"log.level": "ERROR"
}
},
"aggs": {
"logs_over_time": {
"date_histogram": {
"field": "timestamp",
"interval": "minute"
}
}
}
}
為了實現(xiàn)實時監(jiān)控和錯誤告警,我們可以使用 Kibana 的告警功能,設(shè)置觸發(fā)條件和告警機制。
Alerts and Actions
頁面。Kibana 提供了豐富的可視化功能,你可以通過以下方式展示和分析日志數(shù)據(jù):
service.name
,Y 軸為日志數(shù)量,按 log.level
進行分組。通過 Elasticsearch、Filebeat 和 Kibana 的配合,我們可以快速搭建一個集中式日志收集與分析系統(tǒng),實現(xiàn)對分布式系統(tǒng)日志的實時監(jiān)控和告警。步驟包括:
這種架構(gòu)能夠幫助 SaaS 公司快速定位系統(tǒng)錯誤、分析性能瓶頸,并為系統(tǒng)運維提供實時的可視化支持。
業(yè)務(wù)場景: 某在線視頻平臺希望通過構(gòu)建個性化推薦系統(tǒng),根據(jù)用戶的歷史觀看記錄、興趣偏好和行為數(shù)據(jù),為用戶推薦相關(guān)視頻內(nèi)容。這類推薦系統(tǒng)有助于提升用戶的粘性和轉(zhuǎn)化率,進一步推動平臺的商業(yè)化。為了實現(xiàn)該目標,可以采用基于 Elasticsearch 的內(nèi)容推薦模型,結(jié)合協(xié)同過濾(Collaborative Filtering)、內(nèi)容過濾(Content-Based Filtering)以及基于行為的數(shù)據(jù)分析。
解決方案:
More Like This
查詢,根據(jù)用戶歷史觀看的視頻,推薦相似的視頻。結(jié)合 function_score
查詢,基于用戶行為頻次加權(quán),個性化推薦排序。
詳細分析:
Elasticsearch 的 More Like This
查詢非常適合用于相似內(nèi)容推薦的場景,能夠根據(jù)用戶的興趣偏好進行相關(guān)視頻的推薦。其高效的索引和查詢機制,加上支持復(fù)雜的查詢組合,使得推薦系統(tǒng)既能保持較高的實時性,又能根據(jù)動態(tài)數(shù)據(jù)調(diào)整推薦結(jié)果。
推薦系統(tǒng)的核心是數(shù)據(jù),首先我們需要創(chuàng)建 Elasticsearch 索引來存儲用戶和視頻的數(shù)據(jù)。
視頻索引中包含視頻的基礎(chǔ)信息,如標題、描述、標簽、類別等,這些信息可以用來計算視頻的相似度。
PUT /videos
{
"mappings": {
"properties": {
"title": {
"type": "text"
},
"description": {
"type": "text"
},
"tags": {
"type": "keyword"
},
"category": {
"type": "keyword"
},
"release_date": {
"type": "date"
}
}
}
}
我們還需要存儲用戶的行為數(shù)據(jù),比如他們看過哪些視頻,搜索過哪些關(guān)鍵詞等。這些數(shù)據(jù)將用于個性化推薦。
PUT /user_actions
{
"mappings": {
"properties": {
"user_id": {
"type": "keyword"
},
"video_id": {
"type": "keyword"
},
"action_type": {
"type": "keyword" # 例如: view, like, search, etc.
},
"timestamp": {
"type": "date"
}
}
}
}
用戶行為數(shù)據(jù)是個性化推薦的核心依據(jù)。我們可以通過 Filebeat 等工具實時采集用戶的觀看行為數(shù)據(jù),并將其存儲到 Elasticsearch 中。
例如,用戶觀看了某個視頻,行為數(shù)據(jù)可能如下:
POST /user_actions/_doc
{
"user_id": "weige",
"video_id": "video789",
"action_type": "view",
"timestamp": "2024-10-14T12:30:00Z"
}
為了分析用戶的興趣,我們可以使用 Elasticsearch 的聚合功能。比如,統(tǒng)計用戶觀看最多的類別和標簽,以此作為興趣偏好的基礎(chǔ)。
GET /user_actions/_search
{
"size": 0,
"query": {
"term": {
"user_id": "weige"
}
},
"aggs": {
"favorite_categories": {
"terms": {
"field": "category.keyword",
"size": 5
}
}
}
}
該查詢可以幫助我們了解用戶最常觀看的前 5 個視頻類別。
基于內(nèi)容的推薦算法通過分析用戶觀看過的視頻內(nèi)容(標題、描述、標簽等),為用戶推薦相似的視頻。我們可以使用 Elasticsearch 的 more_like_this
查詢來找到和用戶已觀看內(nèi)容相似的視頻。
more_like_this
進行基于內(nèi)容的推薦
假設(shè)用戶剛剛觀看了視頻 video789
,我們希望找到與該視頻內(nèi)容相似的其他視頻。
GET /videos/_search
{
"query": {
"more_like_this": {
"fields": ["title", "description", "tags"],
"like": [
{
"_id": "video789"
}
],
"min_term_freq": 1,
"max_query_terms": 12
}
}
}
這個查詢會根據(jù)視頻 video789
的標題、描述和標簽,推薦相似的視頻。min_term_freq
和 max_query_terms
可以用來調(diào)整推薦的相似度。
協(xié)同過濾(Collaborative Filtering)是另一種常用的推薦算法,它通過分析不同用戶的行為數(shù)據(jù),尋找用戶之間的相似性,從而推薦其他用戶喜歡的視頻。
我們可以通過 Elasticsearch 的聚合來查找與當(dāng)前用戶行為相似的其他用戶,比如查找同樣觀看過某個視頻的用戶。
GET /user_actions/_search
{
"size": 0,
"query": {
"term": {
"video_id": "video789"
}
},
"aggs": {
"similar_users": {
"terms": {
"field": "user_id.keyword",
"size": 10
}
}
}
}
通過這個查詢,我們找到了所有觀看過 video789
的用戶列表。接下來,我們可以根據(jù)這些用戶的觀看歷史,推薦他們喜歡的視頻給當(dāng)前用戶。
找到與當(dāng)前用戶相似的其他用戶后,我們可以查詢他們共同觀看的視頻,并為當(dāng)前用戶推薦這些視頻。
GET /user_actions/_search
{
"size": 10,
"query": {
"terms": {
"user_id": ["weige123", "weige456"] # 與當(dāng)前用戶相似的用戶
}
},
"aggs": {
"recommended_videos": {
"terms": {
"field": "video_id.keyword",
"size": 5
}
}
}
}
通過這個查詢,可以推薦其他用戶看過且當(dāng)前用戶還沒有觀看過的視頻。
為了提高推薦的準確性,可以將基于內(nèi)容的推薦和協(xié)同過濾結(jié)合在一起,綜合考慮用戶的興趣和行為數(shù)據(jù)。
首先,我們可以獲取用戶最喜歡的類別和標簽,然后結(jié)合用戶歷史行為推薦符合這些興趣的熱門視頻。
GET /videos/_search
{
"query": {
"bool": {
"should": [
{ "match": { "category": "user_favorite_category" } },
{ "match": { "tags": "user_favorite_tags" } }
]
}
},
"sort": [
{ "release_date": { "order": "desc" } }
]
}
這種推薦方式綜合了用戶的興趣和最新視頻內(nèi)容,有助于提升用戶體驗。
推薦結(jié)果可以通過前端 API 展示給用戶,假設(shè)通過 JavaScript 請求 Elasticsearch 來獲取推薦內(nèi)容,代碼示例如下:
fetch('http://localhost:9200/videos/_search', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
"query": {
"more_like_this": {
"fields": ["title", "description", "tags"],
"like": [
{
"_id": "video789"
}
],
"min_term_freq": 1,
"max_query_terms": 12
}
}
})
})
.then(response => response.json())
.then(data => {
console.log("Recommended videos:", data.hits.hits);
// 展示推薦視頻內(nèi)容
});
構(gòu)建個性化推薦系統(tǒng)的關(guān)鍵在于對用戶興趣和行為的深刻理解。通過 Elasticsearch,可以輕松實現(xiàn)以下功能:
這種推薦系統(tǒng)不僅能提升用戶粘性,還能增加視頻播放量和廣告轉(zhuǎn)化率,為在線視頻平臺帶來更多的商業(yè)收益。
業(yè)務(wù)場景: 在在線商城中,用戶經(jīng)常根據(jù)價格來篩選商品。商城需要提供按價格區(qū)間篩選商品的功能,并實時統(tǒng)計每個價格區(qū)間內(nèi)的商品數(shù)量,以便用戶快速選擇符合其預(yù)算的商品。這類功能可以通過 Elasticsearch 的聚合查詢來高效實現(xiàn)。
解決方案:
numeric
類型,并存儲到 Elasticsearch 中。range
聚合功能,將商品按價格區(qū)間分類,統(tǒng)計各區(qū)間內(nèi)商品數(shù)量。例如:0-100 元,100-500 元,500-1000 元等。filter
查詢,支持用戶在前端選擇價格區(qū)間進行篩選,展示符合條件的商品,并按價格升序或降序排列。
詳細分析:
Elasticsearch 的聚合功能特別適合用于統(tǒng)計類場景。在價格篩選應(yīng)用中,range
聚合能夠?qū)崟r計算各個價格區(qū)間的商品數(shù)量,配合過濾查詢實現(xiàn)快速篩選。這種機制不僅響應(yīng)速度快,還能動態(tài)適應(yīng)不斷變化的數(shù)據(jù)規(guī)模,保持較高的用戶體驗。
該方案的實現(xiàn)步驟如下:
range
查詢進行價格區(qū)間篩選首先,我們需要創(chuàng)建一個 Elasticsearch 索引來存儲商品數(shù)據(jù)。商品數(shù)據(jù)通常包括商品名稱、描述、分類、價格等信息,其中價格字段將用于價格區(qū)間篩選。
PUT /products
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"description": {
"type": "text"
},
"category": {
"type": "keyword"
},
"price": {
"type": "float"
},
"in_stock": {
"type": "boolean"
}
}
}
}
接下來,我們插入一些商品數(shù)據(jù)以供后續(xù)使用。
POST /products/_bulk
{ "index": { "_id": "1" } }
{ "name": "Smartphone A", "description": "A high-end smartphone", "category": "electronics", "price": 499.99, "in_stock": true }
{ "index": { "_id": "2" } }
{ "name": "Laptop B", "description": "A powerful laptop", "category": "electronics", "price": 899.99, "in_stock": true }
{ "index": { "_id": "3" } }
{ "name": "Tablet C", "description": "A mid-range tablet", "category": "electronics", "price": 299.99, "in_stock": true }
{ "index": { "_id": "4" } }
{ "name": "Headphones D", "description": "Noise-cancelling headphones", "category": "accessories", "price": 199.99, "in_stock": true }
{ "index": { "_id": "5" } }
{ "name": "Smartwatch E", "description": "A fitness-oriented smartwatch", "category": "accessories", "price": 149.99, "in_stock": false }
用戶在商城中可以按照價格區(qū)間來篩選商品。例如,用戶希望查找價格在 200 到 500 之間的商品。我們可以使用 range
查詢來實現(xiàn)這一需求。
GET /products/_search
{
"query": {
"range": {
"price": {
"gte": 200,
"lte": 500
}
}
}
}
該查詢返回價格在 200 到 500 之間的商品。用戶可以通過調(diào)整 gte
(大于等于)和 lte
(小于等于)參數(shù)來修改篩選的價格區(qū)間。
為了提供用戶選擇不同價格區(qū)間的選項,我們需要統(tǒng)計每個價格區(qū)間內(nèi)的商品數(shù)量??梢酝ㄟ^ histogram
或 range
聚合實現(xiàn)這一功能。
range
聚合統(tǒng)計價格區(qū)間商品數(shù)量:GET /products/_search
{
"size": 0,
"aggs": {
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{ "to": 200 }, # 價格在200以下
{ "from": 200, "to": 500 }, # 價格200到500之間
{ "from": 500, "to": 1000 },# 價格500到1000之間
{ "from": 1000 } # 價格1000以上
]
}
}
}
}
該查詢返回每個價格區(qū)間內(nèi)的商品數(shù)量。查詢結(jié)果中的 price_ranges
聚合部分展示了每個區(qū)間內(nèi)的商品數(shù)。
查詢結(jié)果會顯示每個價格區(qū)間內(nèi)的商品數(shù)量:
{
"aggregations": {
"price_ranges": {
"buckets": [
{
"key": "*-200.0",
"doc_count": 2 # 價格在200以下的商品數(shù)量
},
{
"key": "200.0-500.0",
"doc_count": 2 # 價格在200到500之間的商品數(shù)量
},
{
"key": "500.0-1000.0",
"doc_count": 1 # 價格在500到1000之間的商品數(shù)量
},
{
"key": "1000.0-*",
"doc_count": 0 # 價格在1000以上的商品數(shù)量
}
]
}
}
}
結(jié)果中 doc_count
表示每個價格區(qū)間內(nèi)的商品數(shù)量。
在實際應(yīng)用中,用戶希望先查看商品的價格區(qū)間分布,再選擇合適的區(qū)間進行進一步篩選。我們可以結(jié)合上述步驟,先返回各價格區(qū)間的統(tǒng)計數(shù)據(jù),再根據(jù)用戶選擇執(zhí)行相應(yīng)的 range
查詢。
例如,用戶在看到價格區(qū)間統(tǒng)計后,選擇查看 200 到 500 的商品。此時可以執(zhí)行以下查詢:
GET /products/_search
{
"query": {
"range": {
"price": {
"gte": 200,
"lte": 500
}
}
}
}
通過結(jié)合 Elasticsearch 的實時索引更新功能,當(dāng)商品信息(如價格或庫存狀態(tài))發(fā)生變化時,索引也會動態(tài)更新。例如,某個商品的價格調(diào)整或庫存狀態(tài)變化時,我們可以通過實時更新索引來反映這些變化。
假設(shè)我們要更新某個商品的價格和庫存狀態(tài):
POST /products/_update/1
{
"doc": {
"price": 479.99,
"in_stock": false
}
}
通過 Elasticsearch 的 range
查詢和聚合功能,能夠高效地實現(xiàn)在線商城的商品價格區(qū)間篩選和統(tǒng)計功能,具體實現(xiàn)包括:
通過這種方式,用戶可以更直觀、更方便地根據(jù)價格來篩選商品,提升購物體驗。
業(yè)務(wù)場景:
某外賣平臺希望根據(jù)用戶的地理位置,推薦附近的餐館,并根據(jù)與用戶的距離進行排序。為了實現(xiàn)這一需求,可以利用 Elasticsearch 的地理位置查詢(geo-location query)和距離排序功能。通過地理坐標信息(經(jīng)緯度)存儲餐館的位置,并結(jié)合用戶的當(dāng)前位置進行距離計算,快速查詢附近的餐館。
解決方案:
geo_point
類型,創(chuàng)建相應(yīng)的索引。geo_distance
查詢,根據(jù)用戶當(dāng)前的地理位置,搜索附近一定距離內(nèi)的餐館(如 5 公里內(nèi))。geo_distance
的 sort
功能,根據(jù)距離遠近對餐館進行排序,優(yōu)先展示距離較近的餐館。
詳細分析:
Elasticsearch 內(nèi)置的 geo_point
類型和相關(guān)的地理位置查詢功能,非常適合用于位置相關(guān)的業(yè)務(wù)場景。通過 geo_distance
查詢,平臺可以迅速篩選出與用戶距離較近的餐館,并進行距離排序,提升用戶體驗。此外,Elasticsearch 能夠輕松擴展到全球范圍內(nèi)的位置數(shù)據(jù)應(yīng)用,具有極高的靈活性和擴展性。
首先,為了存儲餐館的地理位置,我們需要為餐館數(shù)據(jù)創(chuàng)建一個包含 geo_point
類型的索引,geo_point
用于存儲地理坐標信息(經(jīng)緯度)。
PUT /restaurants
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"description": {
"type": "text"
},
"location": {
"type": "geo_point" # 存儲餐館的經(jīng)緯度信息
},
"rating": {
"type": "float"
},
"category": {
"type": "keyword"
}
}
}
}
接下來,我們將插入一些帶有地理位置的餐館數(shù)據(jù)。這些數(shù)據(jù)中包含餐館的名稱、描述、評分、類別以及位置的經(jīng)緯度信息。
POST /restaurants/_bulk
{ "index": { "_id": "1" } }
{ "name": "韭菜雞蛋", "description": "男人的加油站", "location": { "lat": 40.730610, "lon": -73.935242 }, "rating": 4.5, "category": "Italian" }
{ "index": { "_id": "2" } }
{ "name": "Sushi World", "description": "Authentic china sushi", "location": { "lat": 40.742610, "lon": -73.945242 }, "rating": 4.7, "category": " china" }
{ "index": { "_id": "3" } }
{ "name": "Burger Town", "description": "Best burgers in town", "location": { "lat": 40.729510, "lon": -73.914342 }, "rating": 4.3, "category": "china" }
{ "index": { "_id": "4" } }
{ "name": "Vegan Delight", "description": "Healthy and delicious vegan food", "location": { "lat": 40.715610, "lon": -73.935142 }, "rating": 4.6, "category": "china" }
在這些數(shù)據(jù)中,每個餐館的 location
字段存儲了其經(jīng)緯度信息。
為了根據(jù)用戶的當(dāng)前位置搜索附近的餐館,可以使用 Elasticsearch 的 geo_distance
查詢來實現(xiàn)。假設(shè)用戶當(dāng)前位于某個位置(經(jīng)緯度:40.730610, -73.935242
),我們希望查找這個位置附近的餐館。
GET /restaurants/_search
{
"query": {
"geo_distance": {
"distance": "5km", # 搜索5公里范圍內(nèi)的餐館
"location": {
"lat": 40.730610,
"lon": -73.935242
}
}
}
}
這個查詢會返回距離用戶當(dāng)前位置 5 公里以內(nèi)的所有餐館。
為了讓用戶能夠優(yōu)先看到離自己最近的餐館,我們可以在查詢中添加基于距離的排序功能。Elasticsearch 提供了 geo_distance
排序方法,可以按距離升序排列餐館。
GET /restaurants/_search
{
"query": {
"geo_distance": {
"distance": "5km",
"location": {
"lat": 40.730610,
"lon": -73.935242
}
}
},
"sort": [
{
"_geo_distance": {
"location": {
"lat": 40.730610,
"lon": -73.935242
},
"order": "asc", # 按距離升序排序
"unit": "km"
}
}
]
}
這個查詢不僅返回了 5 公里范圍內(nèi)的餐館,還根據(jù)距離從近到遠進行排序。
為了控制搜索的范圍,比如用戶希望只查找特定半徑范圍內(nèi)的餐館(如 3 公里以內(nèi)),我們可以通過調(diào)整 distance
參數(shù)來實現(xiàn)。
GET /restaurants/_search
{
"query": {
"geo_distance": {
"distance": "3km", # 搜索3公里范圍內(nèi)的餐館
"location": {
"lat": 40.730610,
"lon": -73.935242
}
}
},
"sort": [
{
"_geo_distance": {
"location": {
"lat": 40.730610,
"lon": -73.935242
},
"order": "asc", # 按距離排序
"unit": "km"
}
}
]
}
餐館的位置和營業(yè)狀態(tài)可能會隨著時間發(fā)生變化,例如某家餐館關(guān)閉或新餐館開張。因此,我們需要支持餐館數(shù)據(jù)的實時更新。Elasticsearch 提供了實時索引更新功能,可以方便地更新餐館的位置信息。
如果某家餐館位置發(fā)生了變化(比如遷址),我們可以通過以下命令更新其位置信息:
POST /restaurants/_update/1
{
"doc": {
"location": {
"lat": 40.735610,
"lon": -73.930242 # 更新后的新位置
}
}
}
餐館信息實時更新后,新的查詢結(jié)果將自動反映變化。
除了按距離篩選外,用戶還可能希望按餐館評分來過濾結(jié)果。我們可以將評分篩選條件添加到查詢中,確保返回的餐館不僅距離較近,還符合評分要求。
GET /restaurants/_search
{
"query": {
"bool": {
"must": [
{
"geo_distance": {
"distance": "5km",
"location": {
"lat": 40.730610,
"lon": -73.935242
}
}
},
{
"range": {
"rating": {
"gte": 4.5 # 篩選評分大于或等于4.5的餐館
}
}
}
]
}
},
"sort": [
{
"_geo_distance": {
"location": {
"lat": 40.730610,
"lon": -73.935242
},
"order": "asc", # 按距離排序
"unit": "km"
}
}
]
}
這個查詢將返回距離用戶 5 公里以內(nèi)且評分不低于 4.5 分的餐館。
通過 Elasticsearch 的地理位置查詢功能,我們可以高效地實現(xiàn)外賣平臺的附近餐館搜索和排序功能,具體實現(xiàn)包括:
geo_point
字段存儲餐館的經(jīng)緯度信息。通過這些功能,用戶可以方便地找到附近的優(yōu)質(zhì)餐館,提升了外賣平臺的用戶體驗和服務(wù)效率。
這五個案例涵蓋了 Elasticsearch 在全文搜索、日志分析、推薦系統(tǒng)、數(shù)據(jù)聚合與篩選、地理位置搜索等典型業(yè)務(wù)場景中的應(yīng)用。通過合理的索引設(shè)計、靈活的查詢與聚合功能,Elasticsearch 能夠滿足多種復(fù)雜場景下的高效數(shù)據(jù)檢索與分析需求。
更多建議: