在 JavaScript 中正確使用 Elasticsearch,第二部分

作者:來自 Elastic?Jeffrey Rengifo

回顧生產環境中的最佳實踐,并講解如何在無服務器環境中運行 Elasticsearch Node.js 客戶端。

想獲得 Elastic 認證?查看下一期 Elasticsearch Engineer 培訓的時間!

Elasticsearch 擁有大量新功能,能幫助你為你的使用場景構建最佳搜索解決方案。深入查看我們的示例筆記本,了解更多信息,開始免費云試用,或立即在本地機器上試用 Elastic。


這是我們 Elasticsearch in JavaScript 系列的第二部分。在第一部分中,我們學習了如何正確設置環境、配置 Node.js 客戶端、索引數據以及進行搜索。在第二部分中,我們將學習如何實現生產環境中的最佳實踐,并在無服務器環境中運行 Elasticsearch Node.js 客戶端。

我們將回顧

  • 生產環境最佳實踐
    • 錯誤處理
    • 測試
  • 無服務器環境
    • 在 Elastic Serverless 上運行客戶端
    • 在函數即服務環境中運行客戶端

你可以在這里查看包含示例的源代碼。

生產環境最佳實踐

錯誤處理

Elasticsearch 的 Node.js 客戶端的一個有用功能是,它會暴露出可能出現的 Elasticsearch 錯誤對象,這樣你就可以用不同的方式進行驗證和處理。

要查看所有錯誤對象,運行以下命令:

const { errors } = require('@elastic/elasticsearch')
console.log(errors)

讓我們回到搜索示例,處理一些可能出現的錯誤:

app.get("/search/lexic", async (req, res) => {....} catch (error) {if (error instanceof errors.ResponseError) {let errorMessage ="Response error!, query malformed or server down, contact the administrator!";if (error.body.error.type === "parsing_exception") {errorMessage = "Query malformed, make sure mappings are set correctly";}res.status(error.meta.statusCode).json({erroStatus: error.meta.statusCode,success: false,results: null,error: errorMessage,});}res.status(500).json({success: false,results: null,error: error.message,});}
});

特別是 ResponseError,會在響應為 4xx 或 5xx 時出現,意味著請求不正確或服務器不可用。

我們可以通過生成錯誤的查詢來測試這種類型的錯誤,比如嘗試在 text 類型字段上執行 term 查詢:

默認錯誤:

{"success": false,"results": null,"error": "parsing_exception\n\tRoot causes:\n\t\tparsing_exception: [terms] query does not support [visit_details]"
}

自定義錯誤:

{"erroStatus": 400,"success": false,"results": null,"error": "Response error!, query malformed or server down; contact the administrator!"
}

我們也可以以特定方式捕捉和處理每種類型的錯誤。例如,我們可以在出現 TimeoutError 時添加重試邏輯。

app.get("/search/semantic", async (req, res) => {try {...} catch (error) {if (error instanceof errors.TimeoutError) {// Retry logic...res.status(error.meta.statusCode).json({erroStatus: error.meta.statusCode,success: false,results: null,error:"The request took more than 10s after 3 retries. Try again later.",});}}
});

測試

測試是保障應用穩定性的關鍵。為了在與 Elasticsearch 隔離的情況下測試代碼,我們可以在創建集群時使用庫 elasticsearch-js-mock。

這個庫允許我們實例化一個與真實客戶端非常相似的客戶端,但它會根據我們的配置進行響應,只替換客戶端的 HTTP 層為模擬層,其他部分保持與原始客戶端一致。

我們將安裝 mocks 庫和用于自動化測試的 AVA。

npm install @elastic/elasticsearch-mocknpm install --save-dev ava

我們將配置 package.json 文件來運行測試。確保它如下所示:

"type": "module","scripts": {"test": "ava"},"devDependencies": {"ava": "^5.0.0"}

現在讓我們創建一個 test.js 文件并安裝我們的模擬客戶端:

const { Client } = require('@elastic/elasticsearch')
const Mock = require('@elastic/elasticsearch-mock')const mock = new Mock()
const client = new Client({node: 'http://localhost:9200',Connection: mock.getConnection()
})

現在,添加一個語義搜索的模擬:

function createSemanticSearchMock(query, indexName) {mock.add({method: "POST",path: `/${indexName}/_search`,body: {query: {semantic: {field: "semantic_field",query: query,},},},},() => {return {hits: {total: { value: 2, relation: "eq" },hits: [{_id: "1",_score: 0.9,_source: {owner_name: "Alice Johnson",pet_name: "Buddy",species: "Dog",breed: "Golden Retriever",vaccination_history: ["Rabies", "Parvovirus", "Distemper"],visit_details:"Annual check-up and nail trimming. Healthy and active.",},},{_id: "2",_score: 0.7,_source: {owner_name: "Daniel Kim",pet_name: "Mochi",species: "Rabbit",breed: "Mixed",vaccination_history: [],visit_details:"Nail trimming and general health check. No issues.",},},],},};});
}

現在,我們可以為代碼創建一個測試,確保 Elasticsearch 部分始終返回相同的結果:

import test from 'ava';test("performSemanticSearch must return formatted results correctly", async (t) => {const indexName = "vet-visits";const query = "Which pets had nail trimming?";createSemanticSearchMock(query, indexName);async function performSemanticSearch(esClient, q, indexName = "vet-visits") {try {const result = await esClient.search({index: indexName,body: {query: {semantic: {field: "semantic_field",query: q,},},},});return {success: true,results: result.hits.hits,};} catch (error) {if (error instanceof errors.TimeoutError) {return {success: false,results: null,error: error.body.error.reason,};}return {success: false,results: null,error: error.message,};}}const result = await performSemanticSearch(esClient, query, indexName);t.true(result.success, "The search must be successful");t.true(Array.isArray(result.results), "The results must be an array");if (result.results.length > 0) {t.true("_source" in result.results[0],"Each result must have a _source property");t.true("pet_name" in result.results[0]._source,"Results must include the pet_name field");t.true("visit_details" in result.results[0]._source,"Results must include the visit_details field");}
});

讓我們運行測試。

npm run test

完成!從現在起,我們可以 100% 專注于代碼本身進行測試,而不受外部因素影響。

無服務器環境

在 Elastic Serverless 上運行客戶端

我們之前講過在 Cloud 或本地運行 Elasticsearch;不過,Node.js 客戶端也支持連接到 Elastic Cloud Serverless。

Elastic Cloud Serverless 允許你創建項目,無需擔心基礎設施,因為 Elastic 會內部處理,你只需關注要索引的數據及其保留時長。

從使用角度看,Serverless 將計算和存儲解耦,為搜索和索引提供自動擴展功能,這樣你只需擴展實際需要的資源。

客戶端對連接 Serverless 做了以下適配:

  • 關閉嗅探(sniffing)功能,忽略所有與嗅探相關的選項
  • 忽略配置中除第一個節點外的所有節點,忽略任何節點過濾和選擇選項
  • 啟用壓縮和 TLSv1_2_method(與配置 Elastic Cloud 時相同)
  • 為所有請求添加 elastic-api-version HTTP 頭
  • 默認使用 CloudConnectionPool,而非 WeightedConnectionPool
  • 關閉內置的 content-typeaccept 頭,使用標準 MIME 類型

連接無服務器項目時,需要使用參數 serverMode: serverless

const { Client } = require('@elastic/elasticsearch')
const client = new Client({node: 'ELASTICSEARCH_ENDPOINT',auth: { apiKey: 'ELASTICSEARCH_API_KEY' },serverMode: "serverless",
});

在函數即服務(function-as-a-service)環境中運行客戶端

在示例中,我們使用了 Node.js 服務器,但你也可以使用函數即服務環境連接,比如 AWS Lambda、GCP Run 等函數。

'use strict'const { Client } = require('@elastic/elasticsearch')const client = new Client({// client initialisation
})exports.handler = async function (event, context) {// use the client
}

另一個例子是連接到像 Vercel 這樣的無服務器服務。你可以查看這個完整示例,了解如何操作,但搜索端點中最相關的部分如下:

const response = await client.search({index: INDEX,// You could directly send from the browser// the Elasticsearch's query DSL, but it will// expose you to the risk that a malicious user// could overload your cluster by crafting// expensive queries.query: {match: { field: req.body.text },},},{headers: {Authorization: `ApiKey ${token}`,},}
);

該端點位于 /api 文件夾中,從服務器端運行,這樣客戶端只控制對應搜索詞的 “text” 參數。

使用函數即服務的意義在于,與 24/7 運行的服務器不同,函數只在運行時啟動機器,完成后機器進入休眠狀態,減少資源消耗。

如果應用請求不多,這種配置很方便;否則成本可能較高。你還需考慮函數的生命周期和運行時間(有時僅幾秒)。

總結

本文中,我們學習了如何處理錯誤,這在生產環境中至關重要。還介紹了如何在模擬 Elasticsearch 服務的情況下測試應用,這樣測試更可靠,不受集群狀態影響,能專注于代碼。

最后,我們演示了如何通過配置 Elastic Cloud Serverless 和 Vercel 應用,搭建完全無服務器的架構。

原文:Elasticsearch in JavaScript the proper way, part II - Elasticsearch Labs

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/906360.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/906360.shtml
英文地址,請注明出處:http://en.pswp.cn/news/906360.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2025年網站安全防御全解析:應對DDoS與CC攻擊的智能策略

2025年,隨著AI技術與物聯網設備的深度融合,DDoS與CC攻擊的規模與復雜度持續升級。攻擊者不僅利用T級流量洪泛沖擊帶寬,還通過生成式AI偽造用戶行為,繞過傳統防御規則。如何在保障業務高可用的同時抵御混合型攻擊?本文將…

window 安裝 wsl + cuda + Docker

WSL 部分參考這里安裝: Windows安裝WSL2 Ubuntu環境 - 知乎 如果出現錯誤: WslRegisterDistribution failed with error: 0x800701bc 需要運行:https://crayon-shin-chan.blog.csdn.net/article/details/122994190 wsl --update wsl --shu…

《MambaLLIE:基于隱式Retinex感知的低光照增強框架與全局-局部狀態空間建模》學習筆記

Paper:2405.16105 Github:GitHub - wengjiangwei/MambaLLIE 目錄 摘要 一、介紹 二、相關工作 2.1 低光圖像增強 2.2 視覺空間狀態模型 三、方法 3.1 預備知識 3.2 整體流程 3.3 全局優先-局部次之狀態空間塊 四、實驗 4.1 基準數據集與實施細節 4.2 對比實驗 4…

微信小程序:封裝request請求、解決請求路徑問題

一、創建文件 1、創建請求文件 創建工具類文件request.js,目的是用于發送請求 二、js接口封裝 1、寫入接口路徑 創建一個變量BASE_URL專門存儲api請求地址 2、獲取全局的token變量 從緩存中取出token的數據 3、執行請求 (1)方法中接收傳遞的參數 function request(url,…

【單機版OCR】清華TH-OCR v9.0免費版

今天向大家介紹一款非常好用的單機版OCR圖文識別軟件,它不僅功能多,識別能力強,而且還是免費使用的。OCR軟件為什么要使用單機版,懂得都懂,因為如果使用在線識別的OCR軟件,用戶需要將文檔上傳互聯網服務器的…

開源情報搜集系統:科研創新的強大引擎

一、引言 在當今全球化和信息化高度發展的時代,科研活動面臨著前所未有的機遇與挑戰。一方面,知識的更新換代速度極快,科研成果如雨后春筍般不斷涌現;另一方面,科研競爭日益激烈,如何在眾多科研團隊中脫穎…

產品生命周期不同階段的營銷策略

產品生命周期的不同階段(導入期、成長期、成熟期、衰退期)需要匹配差異化的營銷策略。以下是各階段的營銷重點及具體策略: 1. 導入期(Introduction Stage) 核心目標:建立市場認知,快速觸達目標…

Mujoco 學習系列(二)基礎功能與xml使用

這篇文章是 Mujoco 學習系列第二篇,主要介紹一些基礎功能與 xmI 使用,重點在于如何編寫與讀懂 xml 文件。 運行這篇博客前請先確保正確安裝 Mujoco 并通過了基本功能與GUI的驗證,即至少完整下面這個博客的 第二章節 內容: Mujoc…

面向SDV的在環測試深度解析——仿真中間件SIL KIT應用篇

1.引言 在汽車行業向軟件定義汽車(SDV)轉型的過程中,傳統硬件在環(HIL)測試方案因難以適應新的技術架構與需求,其局限性日益凸顯。傳統HIL對硬件依賴性強,擴展性差,更換ECU或傳感器…

windows使用anaconda安裝pytorch cuda版本

Windows安裝PytorchCUDA環境_使用conda安裝pytorch cuda10.2版本-CSDN博客

Axure中使用動態面板實現圖標拖動交換位置

要在Axure中實現圖標拖動交換位置的功能,可以通過動態面板結合交互事件來實現。 實現步驟 準備圖標元素 將每個圖標轉換為動態面板(方便拖動和交互)。 設置拖動交互 選中圖標動態面板 → 添加“拖動時”交互 → 選擇“移動”當前動態面板&am…

從零開始的嵌入式學習day24

標準IO 頭文件需求&#xff1a; #include <stdio.h>1.fopen和fclose (1)fopen fopen的函數功能是打開一個文件。 首先看看fopen的函數聲明&#xff1a; FILE *fopen(const char *path, const char *mode);第一個參數path是文件地址&#xff0c;傳入的是不可變的字符…

抓包分析工具與流量監控軟件

目錄 一、抓包分析工具&#xff1a;定位問題的“放大鏡” 1.1 工作原理簡述 1.2 主流工具盤點 1.3 抓包的實戰應用 二、流量監控軟件&#xff1a;網絡全景的“雷達系統” 2.1 功能特征 2.2 常用工具概覽 2.3 實戰應用場景 五、結語&#xff1a;深入可見&#xff0c;安…

DRIVEGPT4: 通過大語言模型實現可解釋的端到端自動駕駛

《DriveGPT4: Interpretable End-to-End Autonomous Driving via Large Language Model》 2024年10月發表&#xff0c;來自香港大學、浙江大學、華為和悉尼大學。 多模態大型語言模型&#xff08;MLLM&#xff09;已成為研究界關注的一個突出領域&#xff0c;因為它們擅長處理…

Vue3 Form 表單限制輸入小寫字母、數字和下劃線

方案一&#xff1a;Element Plus 表單驗證 <template><el-form :model"form" :rules"rules" ref"formRef" label-width"120px"><el-form-item label"用戶名" prop"username"><el-input v-m…

23、電網數據管理與智能分析 - 負載預測模擬 - /能源管理組件/grid-data-smart-analysis

76個工業組件庫示例匯總 電網數據管理與智能分析組件 1. 組件概述 本組件旨在模擬一個城市配電網的運行狀態&#xff0c;重點關注數據管理、可視化以及基于模擬數據的智能分析&#xff0c;特別是負載預測功能。用戶可以通過界面交互式地探索電網拓撲、查看節點狀態、控制時間…

單片機復用功能重映射Remap功能

目錄 一、查看“DS5319 stm32f10x中等密度mcu數據手冊&#xff08;英文&#xff09;”手冊 二、查看“RM0008 STM32F10xxx參考手冊&#xff08;中文&#xff09;”手冊 三、重映射&#xff08;Remap&#xff09;功能程序編寫 自己學習過程中容易遺忘的知識點&#xff0c;記錄…

鏈表面試題9之環形鏈表進階

那么上一題我們已經知道了雙指針的變法以及拓展的用法&#xff0c;那么這里我們直接難度升級。 想回去復習的這里放個鏈接&#xff1a;鏈表的面試題8之環形鏈表-CSDN博客 題目鏈接&#xff1a;142. 環形鏈表 II - 力扣&#xff08;LeetCode&#xff09; 我們來看這道題目主要…

游戲引擎學習第299天:改進排序鍵 第二部分

回顧并為當天內容做準備 我們會現場編寫完整的游戲代碼。回顧上周發現自己對游戲中正確的排序規則并沒有清晰的理解。主要原因是我們更擅長三維游戲開發&#xff0c;缺乏二維游戲和二維游戲技術的經驗&#xff0c;對于二維精靈排序、模擬三維效果的最佳方案等沒有太多技巧和經…

Redis從入門到實戰 - 高級篇(中)

一、多級緩存 1. 傳統緩存的問題 傳統的緩存策略一般是請求到達Tomcat后&#xff0c;先查詢Redis&#xff0c;如果未命中則查詢數據庫&#xff0c;存在下面的問題&#xff1a; 請求要經過Tomcat處理&#xff0c;Tomcat的性能成為整個系統的瓶頸Redis緩存失效時&#xff0c;會…