如何用 Node.js 和 Elasticsearch 建構搜尋引擎
英文原文:Build a Search Engine with Node.js and Elasticsearch
Elasticsearch 是一款開源的搜尋引擎,由于其高性能和分布式系統架構而備受關注。本文将讨論其關鍵特性,并手把手教你如何用它建立 Node.js 搜尋引擎。
Elasticsearch 概述
Elasticsearch 底層使用 Apache Lucene 庫,Apache Lucene 自身是一款高性能、基于文本的搜尋引擎庫。 Elasticsearch 并不以提供資料存儲和檢索等類資料庫功能為核心目标,相反,它以搜尋引擎(伺服器端)為目标,意在提供資料索引、資料檢索、和資料實時分析功能
Elasticsearch 采用分布式架構,因而通過新增節點、或者部署到系統已有節點上即可實作水準擴充。Elasticsearch 可以在數以百計的伺服器上處理 PB級别的資料。水準擴充同時也意味着高可用性,如果有節點異常,資料可重新被排程執行。
一旦資料導入完成,即可被檢索。Elasticsearch 提供無模式、JSON 格式檔案存儲、資料結構和類型自動檢檢測等功能。
Elasticsearch 同時采用完全 API 驅動,這意味着:幾乎所有的操作都可在 HTTP 上通過使用符合 JSON 資料格式的Restful API 完成。Elasticsearch 提供多種程式語言的用戶端 lib,包括 Node.js。本文檔将使用 the official client library。
Elasticsearch 對軟硬體要求比較靈活。雖然官方建議線上環境采用 64GB 記憶體,和盡可能多 CPU 系統配置,但其在一個資源受限的系統中依然可以很好地運作(前提是你的資料集不大)。如本文中的示例,2GB 記憶體,單核 cpu 系統即可。
Elasticsearch 支援主流作業系統,如 Linux、Mac os 和 Windows,隻需安裝最新版的 Java 運作時環境(參考 Elasticsearch 安裝章節)。對于本文中的示例,還需要安裝 Node.js (v0.11.0 之後的版本都可) 和 npm。
Elasticsearch術語
Elasticsearch使用自己的術語,在某些情況下和典型的資料庫系統中使用的術語不同。下面列出了Elasticsearch中常用的一些術語及其含義。
索引: 在Elasticsearch環境中,該術語有兩個含義。第一個含義是添加資料的操作。當添加資料時,文本會被拆分成分詞(token)(例如:單詞),每個分詞都會被索引。然而,一個索引也指的是所有索引資料的存儲位置。通常,當我們導入資料時,資料會被索引成一個index。每次需要對資料執行任何操作時,都必須指定它的索引名。
類型:Elasticsearch在一個索引中對文檔提供了更詳細的分類,稱為類型。一個索引中的每個文檔還必須有一個類型。例如,我們可以定義一個圖書館(library)索引,然後再将資料索引成多種類型,比如,文章(article)、書(book)、報告(report)和示範(presentation)。由于索引幾乎有固定的開銷,是以建議使用較少的索引和較多的類型,而不是較多的索引和較少的類型。
檢索: 如字面意思,你可以檢索不同的索引和類型資料。Elasticsearch 提供了多種類型的檢索關鍵字,如term、phrase、range、fuzzy,甚至還提供了地理資料的查詢詞。
過濾: Elasticsearch 支援過濾功能。根據不同的過濾規則過濾檢索結果,以便進一步縮小檢索結果集。Elasticsearch 依據相關性對文檔進行排序。如果你為舊文檔新增查詢詞,可能會觸發文檔的相關性排序,使得舊文檔順序發生變化。但如果隻是新增過濾詞,舊文檔的順序保持不變。
聚合: 可在不同類型的聚合資料上展開統計分析,比如minimum, maximum, average, summation, histograms, 等等.
建議: 針對文本輸入,Elasticsearch 提供不同的建議類型,這些建議類型可以是一個單詞、短語,甚至是完整的語句。
安裝Elasticsearch
Elasticsearch 受Apache 2許可證保護,可以被下載下傳,使用,免費修改。安裝Elasticsearch 之前你需要先確定在你的電腦上安裝了Java Runtime Environment (JRE) ,Elasticsearch 是使用java實作的并且依賴java庫運作。你可以使用下面的指令行來檢測你是否安裝了java
java -version
推薦使用java最新的穩定版本(寫這篇文章的時候是1.8)。你可以在這裡找到在你系統上安裝java的指導手冊。
接下來是下載下傳最新版本的Elasticsearch (寫這篇文章的時候是2.3.5),去下載下傳頁下載下傳ZIP 檔案。Elasticsearch 不需要安裝,一個zip檔案就包含了可在所有支援的系統上運作的檔案。解壓下載下傳的檔案,就完成了。有幾種其他的方式運作Elasticsearch ,比如:獲得TAR 檔案或者為不同Linux發行版本的包(看這裡)。
如果你使用的是Mac作業系統并且安裝了 Homebrew ,你就可以使用這行指令安裝Elasticsearch brew install elasticsearch.Homebrew 會自動添加executables 到你的系統并且安裝所需的服務。它也可以使用一行指令幫你更新應用:brew upgrade elasticsearch.
想在Windows上運作Elasticsearch ,可以在解壓的檔案夾裡,通過指令行運作bin\elasticsearch.bat 。對于其他系統,可以從終端運作 ./bin/elasticsearch.這時候,Elasticsearch 就應該可以在你的系統上運作了。
就像我之前提到的,你可以使用Elasticsearch的幾乎所有的操作,都可以通過RESTful APIs完成。Elasticsearch 預設使用9200 端口。為了確定你正确的運作了Elasticsearch。在你的浏覽器中打開http://localhost:9200/ ,将會顯示一些關于你運作的執行個體的基本資訊。
如果想深入閱讀關于安裝和故障排除,可以通路文檔.
圖形使用者界面
Elasticsearch不須圖形使用者界面,隻通過REST APIs就提供了幾乎所有的功能。然而如果我不介紹怎麼通過APIs和 Node.js執行所有所需的操作,你可以通過幾個提供了索引和資料的可視化資訊GUI工具來完成,這些工具甚至含有一些高水準的分析。
Kibana, 是同一家公司開發的工具, 它提供了資料的實時概要,并提供了一些可視化定制和分析選項。Kibana 是免費的,這是詳細文檔
還有一些是社群開發的工具,如 elasticsearch-head, Elasticsearch GUI, 甚至谷歌浏覽器的擴充元件ElasticSearch Toolbox.這些工具可以幫你在浏覽器中檢視你的索引和資料,甚至可以試運作不同的搜尋和彙總查詢。所有這些工具提供了安裝和使用的攻略。
建立一個Node.js環境
彈性搜尋為Node.js提供一個官方子產品,稱為elasticsearch。首先,你需要添加子產品到你的工程目錄下,并且儲存依賴以備以後使用。
npm install elasticsearch --save
然後,你可以在腳本裡導入子產品,如下所示:
const elasticsearch = require('elasticsearch');
最終,你需要建立用戶端來處理與彈性搜尋的通訊。在這種情況下,我假設你正在運作彈性搜尋的本地機器IP位址是127.0.0.1,端口是9200(預設設定)。
const esClient = new elasticsearch.Client({
host: '127.0.0.1:9200',
log: 'error'
});
日志選項確定所有錯誤被列印出來。在本篇文章末處,我将使用相同的esClient對象與Elasticsearch進行通訊。這裡提供Node子產品的複雜文檔說明。
注意:這篇導讀的所有源代碼都可以在GitHub下載下傳檢視。最簡單的檢視方式是在你的PC機上克隆倉庫,并且從那裡運作示例代碼:
git clone https://github.com:sitepoint-editors/node-elasticsearch-tutorial.git
cd node-elasticsearch-tutorial
npm install
在本教程中,我将使用 1000 篇學術論文裡的内容,這些内容是根據随機算法逐一生成的,并以 JSON 格式提供,其中的資料格式如下所示:
{
"_id": "57508457f482c3a68c0a8ab3",
"title": "Nostrud anim proident cillum non.",
"journal": "qui ea",
"volume": 54,
"number": 11,
"pages": "109-117",
"year": 2014,
"authors": [
{
"firstname": "Allyson",
"lastname": "Ellison",
"institution": "Ronbert",
"email": "[email protected]"
},
...
],
"abstract": "Do occaecat reprehenderit dolore ...",
"link": "http://mollit.us/57508457f482c3a68c0a8ab3.pdf",
"keywords": [
"sunt",
"fugiat",
...
],
"body": "removed to save space"
}
JSON 格式中的每個字段如字面意思,無需多餘解釋,但值得注意的是:由于<body>包含随機生成的文章的全部的内容(大概有100~200個段落),是以并未展示,若要擷取完整資料,請通路這裡.
雖然 Elasticsearch 提供了索引(indexing),更新(updating)、删除(deleting)單個資料的方法,但我們采用批量(bulk)接口導入資料,因為批量接口在大型資料集上執行操作的效率更高。
// index.jsconst bulkIndex = function bulkIndex(index, type, data) {
let bulkBody = [];
data.forEach(item => {
bulkBody.push({
index: {
_index: index,
_type: type,
_id: item.id }
});
bulkBody.push(item);
});
esClient.bulk({body: bulkBody})
.then(response => {
console.log('here');
let errorCount = 0;
response.items.forEach(item => {
if (item.index && item.index.error) {
console.log(++errorCount, item.index.error);
}
});
console.log(
`Successfully indexed ${data.length - errorCount}
out of ${data.length} items`
);
})
.catch(console.err);};const test = function test() {
const articlesRaw = fs.readFileSync('data.json');
bulkIndex('library', 'article', articles);};
這裡,我們調用函數bulkIndex建立索引,并傳入 3 個參數,分别是:索引名 library,類型名library,JSON 資料格式變量 articles。bulkIndex函數自身則通過調用esClient對象的bulk接口實作,bulk 方法包含一個body屬性的對象參數,并且每個body屬性值是一個包含 2 種操作實體的數組對象。第一個實體是 JSON 格式的操作類型對象,該對象中的index屬性決定了操作的類型(本例子是檔案索引)、索引名、檔案ID。第二個實體則是檔案對象本身。
注意,後續可采用同樣的方式,為其他類型檔案(如書籍或者報告)添加索引。我們還可以有選擇的每個檔案配置設定一個唯一的ID,如果不體統唯一的ID,Elasticsearch 将主動為每個檔案配置設定一個随機的唯一ID。
假設你已經從代碼庫中下載下傳了 Elasticsearch 項目代碼,在項目根目錄下執行如下指令,即可将資料導入至Elasticsearch中:
$ node index.js
1000 items parsed from data file
Successfully indexed 1000 out of 1000 items
檢查資料的索引是否準确
Elasticsearch 最大的特性是接近實時檢索,這意味着,一旦文檔索引建立完成,1 秒内就可被檢索(見這裡)。索引一旦建立完成,則可通過運作 indice.js 檢查索引資訊的準确性(源碼連結):
// indices.js
const indices = function indices() {
return esClient.cat.indices({v: true})
.then(console.log)
.catch(err => console.error(`Error connecting to the es client: ${err}`));
};
client 中的cat 對象方法提供目前運作執行個體的各種資訊。其中的 indices 方法列出所有的索引資訊,包括每個索引的健康狀态、以及占用的磁盤大小。 而其中的 v 選項為 cat方法新增頭部響應。
當運作上面代碼段,您會發現,叢集的健康狀态被不同的顔色标示。其中,紅色表示為正常運作的有問題叢集;黃色表示叢集可運作,但存在告警;綠色表示叢集正常運作。在本地運作上面的代碼段,您極有可能(取決于您的配置)看到叢集的健康狀态顔色是黃色,這是因為預設的叢集設定包含 5 個節點,但本地運作隻有 1 個執行個體正常運作。鑒于本教程的目的僅局限于 Elasticsearch 指導學習,黃色即可。但線上上環境中,你必須確定叢集的健康狀态顔色是綠色的。
$ node indices.js
elasticsearch indices information:
health status index pri rep docs.count docs.deleted store.size pri.store.size
yellow open library 5 1 1000 0 41.2mb 41.2mb
動态和自定義映射
如前所述, Elasticsearch 無模式(schema-free),這意味着,在資料導入之前,您無需定義資料的結構(類似于SQL資料庫需要預先定義表結構),Elasticsearch 會主動檢測。盡管 Elasticsearch 被定義為無模式,但資料結構上仍有些限制。
Elasticsearch 以映射的方式引用資料結構。當資料索引建立完成後,如果映射不存在,Elasticsearch 會依次檢索 JSON 資料的每個字段,然後基于被字段的類型(type)自動生成映射(mapping)。如果存在該字段的映射,則會確定按照同樣的映射規則新增資料。否則直接報錯。
比如:如果{"key1": 12} 已經存在,Elasticsearch 自動将字段 key1 映射為長整型。現在如果你嘗試通過{"key1": "value1", "key2": "value2"} 檢索, 則會直接報錯,因為系統預期字段 key1 為長整型。同時,如果通過 {"key1": 13, "key2": "value2"} 檢索則不會報錯,并為字段 key2 新增 string 類型。
映射不能超出文本的範圍,大都數情況下,系統自動生成的映射都可正常運作。如果想深入了解映射,建議查閱Elasticsearch 文檔。
建構查詢引擎
資料索引一旦成功建立,就可立馬建構查詢引擎。 Elasticsearch 提供了一種建構在 JSON 格式之上,直覺、完整的檢索查詢結構,稱之為查詢DSL(Query DSL),來定義查詢。Elasticsearch支援多種類型的檢索詞,但本文隻說明幾個比較常見的類型檢查詞,更詳細的查詢DSL(Query DSL)文檔,請參考這裡:
請記住,每個示例代碼我都提供對應的連結。環境配置完成和測試資料索引成功建立後,你可以通過從代碼庫 克隆代碼到本地,其中的任何示例都可成功執行,隻需要在指令中運作 node filename.js
以一個或者多個索引的形式傳回所有檔案内容
我們将使用client 端提供的各種檢索方法執行檢索操作。最簡單的檢索方式是:match_all,該方法講所有檔案内容以一個或者多個索引的形式傳回。如何以一個索引的方式傳回所有文檔内容,請看下面示例:(源碼連結).
//search_all.js
const search = function search(index, body) {
return esClient.search({index: index, body: body});
};
const test = function test() {
let body = {
size: 20,
from: 0,
query: {
match_all: {}
}
};
search('library', body)
.then(results => {
console.log(`found ${results.hits.total} items in ${results.took}ms`);
console.log(`returned article titles:`);
results.hits.hits.forEach(
(hit, index) => console.log(
`\t${body.from + ++index} - ${hit._source.title}`
)
)
})
.catch(console.error);
};
主要的檢索詞被包含在 query 對象中。稍後我們還可以為該 query 對象新增其他不同類型的檢索詞。需要為每個 query 對象添加一個關鍵檢索類型(本例是 match_all),且值是一個包含檢索選項對象。在這個例子中,由于我們需要傳回所有檔案的索引,是以沒設定可選項。
除了 query 對象之外,檢索主體還可以包含其他可選屬性,比如 size(大小)和 from(出處)。 size(大小)屬性表明響應中包含的文檔的數量,如果不設定該屬性值,預設傳回10個文檔。from(出處)屬性表明待傳回文檔的起始索引的位置,用于分頁場景。
了解查詢API的傳回結果
如果你列印搜尋API傳回結果(上面例子的結果)日志。由于它包含了很多資訊,剛開始看起來無所适從。
{ took: 6,
timed_out: false,
_shards: { total: 5, successful: 5, failed: 0 },
hits:
{ total: 1000,
max_score: 1,
hits:
[ [Object],
[Object],
...
[Object] ] } }
在最進階别日志輸出裡,傳回結果中含有took 屬性,該屬性值表示查找結果所用的毫秒數,timed_out隻有在最大允許時間内沒有找到結果時為true,_shards 是不同節點的狀态的資訊(如果部署的是節點叢集),hits是查詢結果。
hits的屬性值是一個含有下列屬性的對象:
- total —表示比對的條目的總數量
- max_score — 找到的條目的最大分數
- hits — 找到的條目的數組,在hits數組裡的每一天記錄,都有索引,類型,文檔,ID,分數,和記錄本身(在_source元素内)。
這十分複雜,但是好消息是一旦你實作了一個提取結果的方法,不管你的搜尋查詢結果時什麼,你都可以使用相同的格式擷取結果。
還需要注意的是Elasticsearch 有一個好處是它自動地給每一個比對記錄配置設定分數,這個分數用來量化檔案的關聯性,傳回結果的順序預設的按鈕分數倒排。在例子中我們使用match_all取回了所有的記錄,分數是沒有意義的,所有的分數都被計算為1.
比對含指定字段值的文檔
現在我們看幾個更加有趣的例子. 我們可以通過使用 match 關鍵字查詢文檔是否與指定的字段值比對。一個最簡單的包含 match 關鍵字的檢索主體代碼如下所示:(源碼連結).
// search_match.js
{
query: {
match: {
title: {
query: 'search terms go here'
}
}
}
}
如上文所述, 首先通過為查詢對象新增一個條目,并指定檢索類型,上面示例給的是 match 。然後再檢索類型對象裡面,申明待檢索的文檔對象,本例是 title 文檔對象。然後再文檔對象裡面,提供相關檢索資料,和 query 屬性。我希望你測試過上述示例之後,驚訝于 Elasticsearch 的檢索效率。
上述示例執行成功後,将傳回title(标題)字段與任一 query 屬性詞比對的所有文檔資訊。同時還可以參考如下示例,為查詢對象附加最小比對數量條件:
// search_match.js
...
match: {
title: {
query: 'search terms go here',
minimum_should_match: 3
}
}
...
與該查詢比對的文檔 title(标題)字段至少包含上訴指定的 3 個關鍵詞。如果查詢關鍵詞少于 3個,那麼比對文檔的 title(标題)字段必須包含所有的查詢詞。Elasticsearch 的另一個有用的功能是 fuzziness(模糊比對).這對于使用者輸入錯誤的查詢詞将非常有用,因為fuzzy(模糊比對)将發現拼寫錯誤并給出最接近詞供選擇。對于字元串類型,每個關鍵字的模糊比對值是根據算法 Levenshtein distance 算出的最大允許值。fuzziness(模糊比對)示例如下所示:
match: {
title: {
query: 'search tems go here',
minimum_should_match: 3,
fuzziness: 2
}
}
多個字段搜尋
如果你想在多個字段中搜尋,可以使用multi_match搜尋類型。除了Query對象中的fields屬性外,它同match有點類似。fields屬性是需要搜尋的字段的集合。這裡我們将在title,authors.firstname, 和authors.lastname 字段中搜尋(源碼)。
// search_multi_match
multi_match: {
query: 'search terms go here',
fields: ['title', 'authors.firstname', 'authors.lastname']
}
multi_match查詢支援其他搜尋屬性,如minimum_should_match 和fuzziness。Elasticsearch支援使用通配符(如*)比對字段,那麼我們可以使用['title', 'authors.*name']把上面的例子變得更短些。
比對一個完整的句子
Elasticsearch也支援精确的比對一個輸入的句子,而不是在單詞級别。這個查詢是在普通的match 查詢上擴充而來,叫做 match_phrase。下面是一個match_phrase的例子(源碼)
// match_phrase.js
match: {
title: {
query: 'search phrase goes here',
type: 'phrase'
}}
聯合多個查詢
到目前為止,在例子中我們每次請求隻使用了單個查詢。然而Elasticsearch允許你聯合多個查詢。最常用的複合查詢是bool,bool查詢接受4種關鍵類型must, should, must_not, 和filter. 像它們的名字表示的那樣,在查詢結果的資料裡必須比對must裡的查詢,必須不比對must_not裡的查詢,如果哪個資料比對should裡的查詢,它就會獲得高分。每一個提到的元素可以使用查詢數組格式接受多個搜尋查詢。
下面,我們使用bool查詢及一個新的叫做query_string的查詢類型。它允許你使用 AND 或 OR寫一些比較進階的查詢。在這裡可以看到 query_string文法的所有文檔。另外,我們使用了 range查詢(文檔在這裡),它可以讓我們通過給定的範圍的方式去限制一個字段。(源碼)
// search_bool.js
{
bool: {
must: [
{
query_string: {
query: '(authors.firstname:term1 OR authors.lastname:term2) AND (title:term3)'
}
}
],
should: [
{
match: {
body: {
query: 'search phrase goes here',
type: 'phrase'
}
}
}
],
must_not: [
{
range: {
year: {
gte: 2011,
lte: 2013
}
}
}
]
}
}
在上面的例子中,查詢傳回的資料,作者的名包含term1 或它們的姓包含term2,并且它們的title含有term3,而且它們不在2011,2012或2013年出版的,還有在body字段裡含有給定句子資料将獲得高分,并被排列到結果的前面(由于在should從句中的match 查詢)。
過濾,聚合,和建議
除了它先進的搜尋功能外,Elasticsearch 還提供了其他的功能。接下來,我們再看看其他三個比較常用的功能。
過濾
也許,你經常想使用特定的條件凝縮查詢結果。Elasticsearch通過filters 提供了這樣的功能。在我們的文章資料裡,假設你的查詢傳回了幾個文章,這些文章是你選擇的在5個具體年份釋出的文章。你可以簡單的從搜尋結果中過濾出那些不比對條件的資料,而不改變查詢結果的順序。
在bool 查詢的must 從句中,過濾和相同查詢之間的不同之處在于,過濾不會影響搜尋分數,而must 查詢會。當查詢結果傳回并且使用者使用給定的條件過濾時,他們不想改變結果的順序,相反地,他們隻想從結果中移除不相關的資料。過濾與搜尋的格式一樣,但在通常情況下,他們在有明确值的字段上定義,而不是文本字元串上。Elasticsearch 推薦通過bool複合查詢的filter從句添加過濾。
繼續看上面的例子,假設我們想把搜尋結果限制在在2011到2015年之間釋出的文章裡。這樣做,我們隻需要在一般搜尋查詢的filter 部分添加range 查詢。這将會從結果中移除那些不比對的資料。下面是一個過濾查詢的例子(源碼)。
// filter.js
{
bool: {
must: [
{
match: {
title: 'search terms go here'
}
}
],
filter: [
{
range: {
year: {
gte: 2011,
lte: 2015
}
}
}
]
}
}
聚合
聚合架構會基于一次搜尋查詢,提供各種聚合資料和統計資訊。兩個主要的聚合類型是度量和分塊, 度量聚合會對一個文檔的集合進行持續的跟蹤并計算度量,而分塊聚合則會進行塊的建構,每個塊都會跟一個鍵和一個文檔查詢條件關聯起來。度量聚合的示例有平均值,最小值,最大值,加總值還有計數值。分塊聚合的示例有範圍、日期範圍、直方圖以及主題項。對聚合器更加深入的描述可以在 這裡 找到。
聚合可以放置在一個 aggregations 對象裡面,而對象自己則是被直接放到 search 對象體中。在 aggregations 對象裡面,每一個鍵都是由使用者賦予一個聚合器的名稱。聚合器的類型和其它選項都應該是作為這個鍵的值而放置的。接下來我們要來看看兩個不同類型的聚合器,一個是度量的,一個塊的。我們會用度量聚合器來嘗試找出資料集合中最小的年份值(也就是最久遠的文章),而使用塊集合器我要做的就是嘗試找出每一個關鍵詞各自出現了多少次。(源代碼連結)
// aggregations.js{
aggregations: {
min_year: {
min: {field: 'year'}
},
keywords: {
terms: {field: 'keywords'}
}
}}
在上述示例中,我們将度量聚合器命名為 min_year (也可以是其它名稱), 也就是 year 這個域上的 min 類型。塊聚合器責備命名為 keywords, 就是 keywords 這個域上的 terms 類型。聚合操作的結果被裝在了響應消息裡的 aggregations 元素裡面,更深入一點會發現裡面包含了每一個聚合器(這裡是 min_year 和 keywords)以及它們的聚合操作結果。 如下是來自這個示例響應消息中的部分内容。
{
...
"aggregations": {
"keywords": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 2452,
"buckets": [
{
"key": "pariatur",
"doc_count": 88
},
{
"key": "adipisicing",
"doc_count": 75
},
...
]
},
"min_year": {
"value": 1970
}
}
}
響應消息中預設最多會有10個塊傳回。你可以在請求中 filed 的邊上加入一個size鍵來規定傳回的塊的最大數量。如果你想要接收到所有的塊,可以将這個值設定為 0。
建議
Elasticsearch 提供了多種可以對輸入内容提供替換和補全的關聯項推薦器(見文檔)。下面将介紹術語和短語推薦器。術語推薦器為每個輸入文本中的術語提供關聯推薦(如果有的話),而短語推薦器将整個輸入文本看做一個短語(與将其拆分成術語對比),然後提供其他短語的推薦(如果有的話)。使用推薦API時,需要調用Node.js client的suggest方法。如下為術語推薦器的示例。(見源碼)
// suggest_term.js
esClient.suggest({
index: 'articles',
body: {
text: 'text goes here',
titleSuggester: {
term: {
field: 'title',
size: 5
}
}
}
}).then(...)
與其他client的方法相同,在請求體中包含一個index字段指明采用的索引。在body字段中添加查詢推薦的文本,然後給每個推薦器一個(包含了聚合對象的)名稱(本例中的titleSuggester)。其值指明了推薦器的類型和配置。這裡,為title字段使用了術語推薦器,限制最大建議的數量是每個token最多5個(size: 5)。
建議API傳回的資料中包含了對應請求中每一個建議器的key,其值是一個與你輸入文本中術語數量相同的一個數組。對于數組中的每一個元素,包含一個options數組,其每個對象的text字段中包含了推薦的文本。如下是上面例子中傳回資料的一部分。
...
"titleSuggester": [
{
"text": "term",
"offset": 0,
"length": 4,
"options": [
{
"text": "terms",
"score": 0.75,
"freq": 120
},
{
"text": "team",
"score": 0.5,
"freq": 151
}
]
},
...
]
...
擷取短語推薦的時候,采用與上文相同的格式并替換推薦器的類型字段即可。如下的例子中,傳回資料将與上例格式相同。(見源碼)
// suggest_phrase.js
esClient.suggest({
index: 'articles',
body: {
text: 'phrase goes here',
bodySuggester: {
phrase: {
field: 'body'
}
}
}
}).then(...).catch(...)

debugging
翻譯于 2年前
1人頂
頂 翻譯得不錯哦!
進一步閱讀
Elasticsearch 提供了許多特性,這些特性遠遠超出了這一篇文章所能讨論的範圍。在這篇文章中,我試圖站在一個很高的層次上來解釋它的特性,并為你提供可用來進一步學習的合适資源。Elasticsearch是非常可靠的,并且有着出色的表現(我希望你在運作範例時已經注意到了這一點)。再加之不斷增長的社群支援,使得Elasticsearch在工業中的應用也在不斷增加,尤其是對于需要處理實時資料或大資料的公司。
學習完這裡提供的例子之後,我強烈建議你閱讀一些相關文檔。文檔有兩個主要來源,一是Elasticsearch參考及其特性,另外還有一個指南,它更多關注的是具體實作,使用案例以及最佳實踐。你也可以在這裡找到Node.js用戶端的詳細文檔