作者:來自 Elastic?Eduard Martin
想獲得 Elastic 認證?了解下一期 Elasticsearch Engineer 培訓的時間!
Elasticsearch 擁有豐富的新功能,幫助你為你的使用場景構建最佳搜索解決方案。深入查看我們的示例筆記本以了解更多信息,開始免費云試用,或者立即在本地機器上嘗試 Elastic。
UBI(User Behavioral Insights,用戶行為洞察)是一個新興標準,旨在幫助搜索工程師從前端到搜索引擎完整地捕獲和追蹤搜索應用的使用事件。本文將探討 UBI 標準,并解釋如何使用 Elasticsearch 插件捕獲分析數據。

UBI 詳解
UBI 可以用來了解用戶在應用上的行為,并提供關于用戶在搜索什么、用戶在站點的哪些位置進行交互(搜索欄、搜索結果、加入購物車按鈕等)、用戶點擊了哪些結果、當時該查詢返回了哪些結果,以及其他任何你認為有助于優化搜索體驗的元數據的信息。
最常用的指標包括:
- 熱門搜索查詢:被搜索最多的內容
- 無結果查詢:返回無結果的查詢
- 最高點擊:被點擊次數最多的結果
UBI 的一些常見用途包括:
- 可視化:使用分析數據創建儀表盤,以做出戰略決策
- 相關性調優:根據無結果查詢應用查詢規則或同義詞,或調整查詢
- LTR:使用 UBI 創建 判斷列表(judgment lists)?來訓練 LTR 模型,并根據點擊/瀏覽或其他業務需求提升結果
UBI 在 GitHub 上維護,采用 Apache 2.0 許可證。
UBI 模式
UBI 提出了用于查詢(quries)的 schema(在用戶發起搜索時觸發),以及用于事件(events)的 schema(在該次搜索上下文中的其他交互行為觸發)。
例如,如果用戶搜索 “shoe”,就會捕獲一個查詢類型的文檔。隨后,當用戶點擊某個結果時,會創建一個事件類型的文檔,并與之前的查詢類型文檔關聯。
查詢模式 - Query schema
查詢模式用于存儲搜索文本和展示給用戶的結果。它包含以下字段:
- application
- query_id
- client_id
- user_query(必填)
- query_attributes
- object_id_field
- timestamp
- query_response_id
- query_response_hit_ids
一個好的起點是存儲 user_query、timestamp、query_id,這能告訴你查詢執行的時間,以及可用于關聯搜索事件的 ID。
關于這些屬性的更多詳情,請查看最新的 schema。
事件模式
事件模式用于捕獲所有搜索后的用戶行為,例如點擊和購買。它包含以下字段:
- application
- action_name(必填)
- query_id
- session_id
- client_id
- user_id
- timestamp(必填)
- message_type
- message
- user_query
- event_attributes
你可以在此處找到每個字段的定義。
在 Elasticsearch 中使用 UBI
由于 UBI 是一個標準,而不是工具或庫,我們只需要兩個組件就可以在 Elasticsearch 中實現它:
- 應用:我們需要從應用中生成符合 UBI 標準的使用事件
- 索引:我們需要 Elasticsearch 索引來存儲這些數據,之后可以用 Kibana 可視化這些事件
UBI 團隊創建了一個 Elasticsearch 插件,它會根據集群接收到的 _search 請求自動創建索引并存儲查詢。我們將使用這種方式。或者,你也可以自行構建事件收集器,并使用正確的 schema 將事件發送到 Elasticsearch。
為了開始捕獲 UBI 事件,我們將進行以下步驟:
- 安裝用于 UBI 的 Elasticsearch 插件
- 加載示例數據
- 測試插件
后續文章將介紹可視化部分,敬請關注!
安裝用于 UBI 的 Elasticsearch 插件
Elasticsearch 的 User Behavior Insights(UBI)插件旨在捕獲搜索查詢,以更好地了解用戶行為。該插件專注于捕獲服務端的查詢,而 o19s/ubi 倉庫則用于客戶端事件的捕獲。
插件的工作方式是在搜索請求體中接受一個額外的 ext 參數,從而發送一個 UBI 事件。在搜索時,它會在內部創建一個文檔,記錄執行的查詢以及你放在 ext.ubi 中的 schema 字段。你可以使用 query_id 字段來關聯同一次搜索中的不同事件。
編譯插件
首先克隆倉庫:
git clone https://github.com/o19s/user-behavior-insights-elasticsearch.git
使用插件構建 jar 包:
./gradlew build
該 bundle 會在 /build/distributions 文件夾下創建,是一個 zip 文件,例如 elasticsearch-ubi-1.0.0-SNAPSHOT.zip。請保存該文件以便后續使用。
安裝插件
我們將在 Elastic Cloud 實例上安裝該插件。對于自管理部署,你可以按照文檔中的步驟操作。
1)登錄 Elastic Cloud,然后進入 Extensions:
2)點擊 “Upload extension”,選擇 elasticsearch-ubi-1.0.0-SNAPSHOT.zip 文件,并填寫相關信息。撰寫本文時,插件所對應的 Elasticsearch 版本是 8.15.2,因此你必須使用該版本,或者為其他版本重新編譯。你可以通過查看 gradle.properties 文件,確認插件最新代碼所使用的 Elasticsearch 版本。
3)成功上傳擴展后,點擊 Elastic 標志進入 Elastic Cloud 主頁面。
4)在你的工作部署上,點擊 Manage。
5)點擊 Actions 下拉菜單,然后點擊 Edit deployment。
6)在 Elasticsearch 部分,點擊 Manage user settings and extensions 鏈接。
7)點擊 Extensions 選項卡,選擇最近安裝的擴展,本例中是 ubi8。然后,點擊 “Back” 并保存更改。
加載示例數據
在 Kibana DevTools 控制臺中運行以下命令,加載幾本書用于測試插件。此操作會創建一個名為 “books” 的新索引作為示例。
POST /_bulk
{ "index" : { "_index" : "books" } }
{"name": "Snow Crash", "author": "Neal Stephenson", "release_date": "1992-06-01", "page_count": 470, "price": 14.99, "url": "https://www.amazon.com/Snow-Crash-Neal-Stephenson/dp/0553380958/", "image_url": "https://m.media-amazon.com/images/I/81p4Y+0HzbL._SY522_.jpg", "_extract_binary_content": true, "_reduce_whitespace": true, "_run_ml_inference": true}
{ "index" : { "_index" : "books" } }
{"name": "Revelation Space", "author": "Alastair Reynolds", "release_date": "2000-03-15", "page_count": 585, "price": 16.99, "url": "https://www.amazon.com/Revelation-Space-Alastair-Reynolds/dp/0441009425/", "image_url": "https://m.media-amazon.com/images/I/61nC2ExeTvL._SY522_.jpg", "_extract_binary_content": true, "_reduce_whitespace": true, "_run_ml_inference": true}
{ "index" : { "_index" : "books" } }
{"name": "1984", "author": "George Orwell", "release_date": "1985-06-01", "page_count": 328, "price": 12.99, "url": "https://www.amazon.com/1984-Signet-Classics-George-Orwell/dp/0451524934/", "image_url": "https://m.media-amazon.com/images/I/71rpa1-kyvL._SY522_.jpg", "_extract_binary_content": true, "_reduce_whitespace": true, "_run_ml_inference": true}
{ "index" : { "_index" : "books" } }
{"name": "Fahrenheit 451", "author": "Ray Bradbury", "release_date": "1953-10-15", "page_count": 227, "price": 11.99, "url": "https://www.amazon.com/Fahrenheit-451-Ray-Bradbury/dp/1451673310/", "image_url": "https://m.media-amazon.com/images/I/61sKsbPb5GL._SY522_.jpg", "_extract_binary_content": true, "_reduce_whitespace": true, "_run_ml_inference": true}
{ "index" : { "_index" : "books" } }
{"name": "Brave New World", "author": "Aldous Huxley", "release_date": "1932-06-01", "page_count": 268, "price": 12.99, "url": "https://www.amazon.com/Brave-New-World-Aldous-Huxley/dp/0060850523/", "image_url": "https://m.media-amazon.com/images/I/71GNqqXuN3L._SY522_.jpg", "_extract_binary_content": true, "_reduce_whitespace": true, "_run_ml_inference": true}
{ "index" : { "_index" : "books" } }
{"name": "The Handmaid's Tale", "author": "Margaret Atwood", "release_date": "1985-06-01", "page_count": 311, "price": 13.99, "url": "https://www.amazon.com/Handmaids-Tale-Margaret-Atwood/dp/038549081X/", "image_url": "https://m.media-amazon.com/images/I/61su39k8NUL._SY522_.jpg", "_extract_binary_content": true, "_reduce_whitespace": true, "_run_ml_inference": true}
測試插件
調用 _search API 時,你可以發送一個額外的 ext 參數 —— 一個包含本文開頭所述字段的對象。
索引查詢
我們來寫一個查詢,并使用插件捕獲行為元數據。
GET books/_search
{"query": {"match": {"name": "Snow"}},"ext": {"ubi": {"object_id_field": "url","user_query": "snow","client_id": "web_application","query_attributes": {"app_component": "global_header"}}}
}
- object_id_field:用于標識結果的字段,將作為結果集存儲在 ubi_queries 索引中。
- user_query:用戶在搜索框中輸入的內容。
- client_id:查詢的發起方。
- query_attributes:任意的鍵/值對。
在返回結果的同時,響應中會包含一個 query_id,我們可以用它來查看 ubi_queries 索引。
{"ext": {"ubi": {"query_id": "cb26ba2c-27ab-4af3-905b-00aff928cf50"}},"hits": {"total": {"value": 1,"relation": "eq"},"max_score": 1.5904956,"hits": [{"_index": "books","_id": "Ep2h4ZcBDN5ljpdU06rw","_score": 1.5904956,"_source": {"name": "Snow Crash","author": "Neal Stephenson","release_date": "1992-06-01","page_count": 470,"price": 14.99,"url": "https://www.amazon.com/Snow-Crash-Neal-Stephenson/dp/0553380958/","image_url": "https://m.media-amazon.com/images/I/81p4Y+0HzbL._SY522_.jpg","_extract_binary_content": true,"_reduce_whitespace": true,"_run_ml_inference": true}}]}
}
存儲在 ubi_queries 中的文檔看起來像這樣:
{"_index": "ubi_queries","_id": "HJ204ZcBDN5ljpdUKKo2","_score": 4.7303333,"_source": {"query_response_id": "59474463-5862-4941-992e-50cafc294274","user_query": "snow","query_id": "cb26ba2c-27ab-4af3-905b-00aff928cf50","query_response_object_ids": ["https://www.amazon.com/Snow-Crash-Neal-Stephenson/dp/0553380958/"],"query": """{"query": {"match": {"name": {"query": "Snow"}}},"ext": {"query_id": "cb26ba2c-27ab-4af3-905b-00aff928cf50","user_query": "snow","client_id": "web_application","object_id_field": "url","query_attributes": {"app_component": "global_header"}}}""","query_attributes": {"app_component": "global_header"},"client_id": "web_application","timestamp": 1751838369845}}
文檔將包含 Elasticsearch 執行的查詢、我們提供的元數據、匹配的文檔列表,以及查詢響應的額外標識符。
有了這些數據,我們現在可以分析趨勢,比如熱門查詢、無結果的熱門查詢、結果集中的熱門文檔,并且可以對客戶端應用、應用組件和時間過濾器等進行篩選。
捕獲事件
假設在同一次搜索中,用戶點擊了某個結果,我們希望捕獲該事件并將其與剛才索引的查詢相關聯。要捕獲客戶端事件(例如,點擊結果),應用程序必須將事件發送到 ubi_events 索引:
POST ubi_events/_doc
{"action_name": "click","query_id": "cb26ba2c-27ab-4af3-905b-00aff928cf50","client_id": "web_application","timestamp": "2025-05-09T19:56:55.579Z","message_type": "CLICK_THROUGH","message": "Clicked Snow Crash","user_query": "snow","event_attributes": {"object": {"object_id": "Ep2h4ZcBDN5ljpdU06rw"},"position": {"ordinal": 1}}
}
現在我們已經捕獲了該文檔、搜索中的點擊、點擊位置(position.ordinal)以及原始的 id 值(object_id)。
該事件使我們能夠識別被點擊最多的文檔、產生最多點擊的用戶查詢,以及用戶是否點擊了排名靠前的結果。
洞察分析
我們可以使用 ES|QL 來分析數據。下面通過統計 ubi_queries 索引中 user_query 的文檔數量,找出排名前五的查詢:
POST /_query?format=txt
{"query": """FROM ubi_queries| STATS count = COUNT(*) BY user_query| SORT count DESC| LIMIT 5"""
}
你將獲得格式化為表格的結果:
count | user_query
---------------+---------------
54 |fahrenheit
14 |snow
9 |summer books
4 |top seller
2 |alastair
總結
本文介紹了如何使用 Elasticsearch 插件捕獲 UBI 查詢和事件,以及如何使用提取有意義洞察所需的基本字段。
在下一篇文章中,我們將進一步介紹如何捕獲更豐富的元數據、編寫更高級的 ES|QL 查詢,并構建 Kibana 儀表盤,以幫助我們更好地了解用戶,提升搜索體驗。
原文:Elasticsearch plugin for UBI: Analyze user behavior from search queries - Elasticsearch Labs