这篇文章是由同行审查马克·布朗 , Vildan Softic和莫里茨克罗格 。 感谢所有SitePoint的同行评审人员使SitePoint内容达到最佳状态!
Elasticsearch是一个开放源代码搜索引擎,由于其高性能和分布式体系结构而日益流行。 在本文中,我将讨论其主要功能,并引导您完成使用它创建Node.js搜索引擎的过程。
Elasticsearch简介
Elasticsearch建立在Apache Lucene之上, Apache Lucene是一个高性能的文本搜索引擎库。 尽管Elasticsearch可以执行数据的存储和检索,但其主要目的不是充当数据库,而是一个搜索引擎(服务器),其主要目标是对数据进行索引,搜索和提供实时统计信息。
Elasticsearch具有分布式架构,可通过添加更多节点并利用额外的硬件来进行水平扩展。 它支持数千个节点,用于处理PB的数据。 它的水平缩放还意味着,如果任何节点发生故障,则通过重新平衡数据即可实现高可用性。
导入数据后,即可立即进行搜索。 Elasticsearch是无架构的,将数据存储在JSON文档中,并且可以自动检测数据结构和类型。
Elasticsearch也是完全由API驱动的。 这意味着几乎所有操作都可以通过简单的RESTful API使用HTTP上的JSON数据来完成。 它具有适用于几乎所有编程语言(包括Node.js)的许多客户端库。 在本教程中,我们将使用官方客户端库 。
当涉及到硬件和软件需求时,Elasticsearch非常灵活。 尽管建议的生产设置是64GB内存和尽可能多的CPU内核,但是您仍然可以在资源受限的系统上运行它并获得不错的性能(假设您的数据集不大)。 为了遵循本文中的示例,具有2GB内存和单个CPU内核的系统就足够了。
您可以在所有主要操作系统(Linux,Mac OS和Windows)上运行Elasticsearch。 为此,您需要安装最新版本的Java Runtime Environment(请参阅“ 安装Elasticsearch”部分)。 要遵循本文中的示例,您还需要安装Node.js (v0.11.0之后的任何版本都可以)以及npm 。
Elasticsearch术语
Elasticsearch使用自己的术语,在某些情况下与典型的数据库系统不同。 以下是Elasticsearch中的常用术语及其含义的列表。
索引 :该术语在Elasticsearch上下文中有两个含义。 首先是添加数据的操作。 添加数据后,文本被分解为标记(例如单词),并且每个标记都被索引。 但是,索引还指的是所有索引数据存储在何处。 基本上,当您导入数据时,会将其索引到索引中。 每次您要对数据执行任何操作时,都需要指定其索引名称。
类型 :Elasticsearch在索引中提供了文档的更详细分类,这称为类型。 索引中的每个文档也应该有一个类型。 例如,我们可以定义一个library
索引,然后在其中索引多种数据类型,例如article
, book
, report
和presentation
。 由于索引的开销几乎是固定的,因此建议减少索引和类型,而不要增加索引和类型。
搜索 :该术语表示您可能会想的。 您可以搜索不同索引和类型的数据。 Elasticsearch提供了多种类型的搜索查询,例如术语,短语,范围,模糊甚至地理数据查询。
过滤器 :Elasticsearch允许您根据不同的条件过滤搜索结果,以进一步缩小搜索范围。 如果将新的搜索查询添加到一组文档中,则可能会根据相关性更改顺序,但是如果将同一查询添加为过滤器,则该顺序将保持不变。
聚合 :这些为您提供有关聚合数据的不同类型的统计信息,例如最小值,最大值,平均值,求和,直方图等。
建议 :Elasticsearch为输入文本提供不同类型的建议。 这些建议可以是基于术语或短语的,甚至可以是完成建议。
安装Elasticsearch
Elasticsearch在Apache 2许可下可用; 可以免费下载,使用和修改。 在安装它之前,您需要确保在计算机上安装了Java Runtime Environment(JRE)。 Elasticsearch是用Java编写的,并且依赖Java库来运行。 要检查系统上是否安装了Java,可以在命令行中键入以下内容。
java -version
建议使用最新的Java稳定版本(在撰写本文时为1.8)。 您可以在此处找到有关在系统上安装Java的指南。
接下来,要下载最新版本的Elasticsearch(在撰写本文时为2.4.0),请转到下载页面并下载ZIP文件。 Elasticsearch不需要安装,并且单个zip文件包含用于在所有支持的操作系统上运行程序的完整文件集。 解压下载的文件,就可以完成了! 还有其他几种方法可以使Elasticsearch运行,例如获取TAR文件或用于不同Linux发行版的软件包(请参见此处 )。
如果您正在运行Mac OS X并且安装了Homebrew ,则可以使用brew install elasticsearch
来安装Elasticsearch。 Homebrew自动将可执行文件添加到您的路径并安装所需的服务。 它还可以帮助您使用一个命令来更新应用程序: brew upgrade elasticsearch
。
要在Windows上运行Elasticsearch,请从解压缩的目录中,从命令行运行bin\elasticsearch.bat
。 对于其他所有操作系统, ./bin/elasticsearch
从终端运行./bin/elasticsearch
。 此时,它应该已在您的系统上运行。
正如我之前提到的,您几乎可以使用Elasticsearch进行的所有操作都可以通过RESTful API完成。 Elasticsearch默认使用端口9200。 为了确保它运行正确,请在浏览器中转到http://localhost:9200/
,它应显示有关正在运行的实例的一些基本信息。
有关安装和故障排除的更多信息,请访问文档 。
图形用户界面
Elasticsearch通过REST API提供几乎所有功能,并且不附带图形用户界面(GUI)。 在介绍如何通过API和Node.js执行所有必要的操作的同时,有几种GUI工具提供有关索引和数据的可视信息,甚至提供一些高级分析。
由同一家公司开发的Kibana提供了数据的实时摘要以及一些自定义的可视化和分析选项。 Kibana是免费的,并且具有详细的文档 。
社区还开发了其他工具,包括elasticsearch-head , Elasticsearch GUI甚至是一个名为ElasticSearch Toolbox的Chrome扩展。 这些工具可帮助您在浏览器中浏览索引和数据,甚至可以尝试其他搜索和聚合查询。 所有这些工具都提供了安装和使用的演练。
设置Node.js环境
Elasticsearch为Node.js提供了一个官方模块,称为elasticsearch
。 首先,您需要将模块添加到项目文件夹中,并保存依赖项以备将来使用。
npm install elasticsearch --save
然后,您可以按照以下步骤将模块导入脚本中:
const elasticsearch = require('elasticsearch');
最后,您需要设置处理与Elasticsearch的通信的客户端。 在这种情况下,我假设您正在IP地址为127.0.0.1
和端口9200
(默认设置)的本地计算机上运行Elasticsearch。
const esClient = new elasticsearch.Client({
host: '127.0.0.1:9200',
log: 'error'
});
log
选项可确保记录所有错误。 在本文的其余部分中,我将使用相同的esClient
对象与Elasticsearch进行通信。 此处提供了有关节点模块的完整文档。
注意 :本教程的所有源代码都在GitHub上提供 。 最简单的方法是将存储库克隆到您的PC并从那里运行示例:
git clone https://github.com:sitepoint-editors/node-elasticsearch-tutorial.git
cd node-elasticsearch-tutorial
npm install
导入数据
在整个教程中,我将使用具有随机生成内容的学术文章数据集。 数据以JSON格式提供,数据集中有1000篇文章。 为了显示数据的样子,下面显示了数据集中的一项。
{
"_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": "Allyson@Ronbert.tv"
},
...
],
"abstract": "Do occaecat reprehenderit dolore ...",
"link": "http://mollit.us/57508457f482c3a68c0a8ab3.pdf",
"keywords": [
"sunt",
"fugiat",
...
],
"body": "removed to save space"
}
字段名称不言自明。 唯一需要注意的是,此处没有显示body
字段,因为它包含完整的随机生成的文章(100至200个段落)。 您可以在此处找到完整的数据集。
虽然Elasticsearch提供了索引 , 更新和删除单个数据点的方法,但是我们将使用Elasticserch的bulk方法导入数据,该方法用于以更有效的方式对大型数据集执行操作:
// index.js
const 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
函数,将其library
作为索引名称,将article
作为类型以及希望索引的JSON数据传递给它。 bulkIndex
函数依次调用esClient
对象上的bulk
方法。 此方法将具有body
属性的对象作为参数。 提供给body
属性的值是一个数组,其中每个操作都有两个条目。 在第一个条目中,操作的类型指定为JSON对象。 在此对象内, index
属性确定要执行的操作(在这种情况下为文档建立索引),以及索引名称,类型名称和文档ID。 下一个条目对应于文档本身。
请注意,将来您可能会以这种方式将其他类型的文档(例如书籍或报告)添加到同一索引中。 我们还可以为每个文档分配一个唯一的ID,但这是可选的-如果您不提供一个ID,Elasticsearch将为您为每个文档分配一个随机生成的唯一ID。
假设您已经克隆了存储库,现在可以通过从项目根目录执行以下命令将数据导入Elasticsearch:
$ node index.js
1000 items parsed from data file
Successfully indexed 1000 out of 1000 items
检查数据是否正确建立索引
Elasticsearch的一大特色是近实时搜索。 这意味着一旦对文档建立索引,它们将在一秒钟之内可供搜索(请参阅此处 )。 对数据建立索引后,您可以通过运行indices.js
( 链接到source )来检查索引信息:
// 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}`));
};
客户端的cat
对象中的方法提供有关当前正在运行的实例的不同信息。 indices
方法列出了所有索引,它们的健康状态,其文档数以及它们在磁盘上的大小。 v
选项将标题添加到cat
方法的响应中。
运行上面的代码片段时,您会注意到它会输出一个颜色代码来指示集群的运行状况。 红色表示群集出现问题,并且未运行。 黄色表示集群正在运行,但是有警告,绿色表示一切正常。 在本地计算机上运行时,最有可能(取决于您的设置)您将获得黄色状态。 这是因为默认设置包含该群集的五个节点,但是在本地计算机中,只有一个实例正在运行。 虽然您应该始终将生产环境中的绿色状态作为目标,但出于本教程的目的,您可以继续以黄色状态使用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是无架构的。 这意味着在导入数据之前,不必定义数据的结构(类似于在SQL数据库中定义表),而是Elasticsearch会自动为您检测数据。 但是尽管被称为无模式的,但数据结构还是有一些限制。
Elasticsearch将数据结构称为映射。 如果不存在映射,则在为数据建立索引时,Elasticsearch会查看JSON数据的每个字段,并根据其类型自动定义映射。 如果该字段已经存在映射条目,则确保要添加的新数据遵循相同的格式。 否则,将引发错误。
例如,如果已经为{"key1": 12}
编制了索引,Elasticsearch会自动将字段key1
映射为long
。 现在,如果您尝试为{"key1": "value1", "key2": "value2"}
编制索引,则会引发错误,并期望字段key1
类型为long
。 同时,对象{"key1": 13, "key2": "value2"}
将没有任何问题进行索引,以key2
类型的string
添加到映射。
映射超出了本文的范围,并且在大多数情况下,自动映射可以正常工作。 我建议您查看elasticsearch文档 ,该文档提供了有关映射的深入讨论。
构建搜索引擎
索引完数据后,我们准备实施搜索引擎。 Elasticsearch提供了一种称为Query DSL的直观完整搜索查询结构(基于JSON)来定义查询。 有很多类型的搜索查询,但是在本文中,我们将研究几种更常见的搜索查询。 可以在此处找到Query DSL的完整文档。
请记住,我在每个显示的示例后面都提供了指向代码的链接。 设置环境并为测试数据建立索引后,您可以克隆存储库并在计算机上运行任何示例。 为此,只需从命令行运行
node filename.js
。
返回一个或多个索引中的所有文档
为了执行搜索,我们将使用客户端提供的各种搜索方法。 最简单的查询是match_all
,它以一个或多个索引返回所有文档。 下面的示例说明了如何获取索引中的所有存储文档( 链接到source )。
//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
对象内。 稍后我们将看到,我们可以向该对象添加不同类型的搜索查询。 对于每个查询,我们添加一个查询类型为key(在此示例中为match_all
)的键,该值是包含搜索选项的对象。 在此示例中没有选项,因为我们要返回索引中的所有文档。
除了query
对象之外,搜索主体还可以包含其他可选属性,包括size
和from
。 size
属性确定响应中要包含的文档数。 如果不存在此值,默认情况下将返回十个文档。 from
属性确定返回文档的起始索引。 这对于分页很有用。
了解搜索API响应
如果您要注销来自搜索API的响应(上例中的results
),则由于包含很多信息,它最初可能看起来不堪重负。
{ 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.0。
匹配包含字段中特定值的文档
现在,让我们看一些更有趣的例子。 要匹配包含字段中特定值的文档,我们可以使用match
查询。 下面显示了一个带有match
查询的简单搜索主体( 链接到source )。
// search_match.js
{
query: {
match: {
title: {
query: 'search terms go here'
}
}
}
}
正如我前面提到的,我们首先将一个条目添加到具有搜索类型的查询对象match
,在上面的示例中这是match
的。 在搜索类型对象内,我们标识要搜索的文档字段,此处为title
。 在其中,我们放入了与搜索相关的数据,包括query
属性。 我希望在测试完上面的示例后,您对搜索的速度感到惊讶。
上面的搜索查询返回其标题字段与query
属性中的任何单词匹配的文档。 我们可以按如下所示设置匹配词的最小数量。
// search_match.js
...
match: {
title: {
query: 'search terms go here',
minimum_should_match: 3
}
}
...
此查询匹配标题中至少包含三个指定单词的文档。 如果查询中少于三个词,则要匹配的文档的标题中必须全部包含三个词。 添加到搜索查询中的另一个有用功能是模糊性。 如果用户在写查询时打错了输入,这将很有用,因为模糊匹配会找到拼写紧密的术语。 对于字符串,模糊度值基于每个术语的最大允许Levenshtein距离 。 下面是一个带有模糊性的示例。
match: {
title: {
query: 'search tems go here',
minimum_should_match: 3,
fuzziness: 2
}
}
在多个字段中搜索
如果要在多个字段中搜索,则可以使用multi_match
搜索类型。 它与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
查询接受四种类型的键: 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
, 并且他们的头衔有term3
,他们没有公布在年2011年,2012年或2013年另外,已给定的文件在他们body
词组,会获得更高的分数,并显示在结果的顶部(因为match
查询位于should
子句中)。
过滤器,汇总和建议
除了其高级搜索功能外,Elasticsearch还提供其他功能。 在这里,我们看三个比较常见的功能。
筛选器
通常,您可能希望根据特定条件优化搜索结果。 Elasticsearch通过过滤器提供此功能。 在我们的文章数据中,假设您的搜索返回了几篇文章,而您只想选择在五年中发表的文章。 您可以简单地从搜索结果中筛选出不符合您的条件的所有内容,而无需更改搜索顺序。
过滤器与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
(此名称可以是任何名称),在field year
上类型为min
。 铲斗聚合名为keywords
,这类型的terms
在外地keywords
。 聚合结果包含在响应中的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个存储桶。 您可以在请求中的field
旁边添加一个size
键,以确定返回的最大存储桶数。 如果要接收所有存储桶,请将此值设置为0。
意见建议
Elasticsearch具有多种类型的建议程序,它们为输入的术语( 此处提供文档)提供替换或完成建议。 我们将在这里查看术语和短语建议者。 术语建议者为输入的文本中的每个术语提供建议(如果有的话),而短语建议者将输入的文本视为整个短语(而不是将其分解为术语),并提供其他短语建议(如果有的话)。 要使用建议API,我们需要在Node.js客户端上调用suggest
方法。 以下是术语建议器的示例。 (链接到源 )
// suggest_term.js
esClient.suggest({
index: 'articles',
body: {
text: 'text goes here',
titleSuggester: {
term: {
field: 'title',
size: 5
}
}
}
}).then(...)
在请求主体中,与所有其他客户端方法一致,我们具有一个index
字段,用于确定搜索的索引。 在body
属性中,我们添加要为其寻求建议的文本,并且(与聚合对象一样)为每个建议者命名(在这种情况下为titleSuggester
)。 它的值确定建议者的类型和选项。 在这种情况下,我们在title
字段中使用term
建议者,并将每个令牌的最大建议数目限制为五个( size: 5
)。
提示API的响应为每个请求的提示提供了一个键,该键是一个数组,其大小与text
字段中的术语数相同。 对于该数组内的每个对象,都有一个options
对象,该对象在其text
字段中包含建议。 以下是上述请求的部分响应。
...
"titleSuggester": [
{
"text": "term",
"offset": 0,
"length": 4,
"options": [
{
"text": "terms",
"score": 0.75,
"freq": 120
},
{
"text": "team",
"score": 0.5,
"freq": 151
}
]
},
...
]
...
要获取词组建议,我们可以采用与上述相同的格式,只需将建议者类型替换为phrase
。 在以下示例中,响应遵循与上述相同的格式。 (链接到源 )
// suggest_phrase.js
esClient.suggest({
index: 'articles',
body: {
text: 'phrase goes here',
bodySuggester: {
phrase: {
field: 'body'
}
}
}
}).then(...).catch(...);
进一步阅读
Elasticsearch提供了广泛的功能,这些功能远远超出了本文的范围。 在本文中,我试图从较高的角度解释其功能,并为您提供适当的参考资料以供进一步研究。 Elasticsearch非常可靠,并且具有出色的性能(希望您在运行示例时注意到这一点)。 再加上社区支持的增加,Elasticsearch在行业中的采用率有所提高,尤其是在处理实时或大数据的公司中。
看完这里提供的示例后,强烈建议您阅读文档。 它们提供了两个主要资源,一个是对Elasticsearch及其功能的参考 ,另一个是作为指南 ,其重点更多地放在实现,用例和最佳实践上。 您还可以在此处找到有关Node.js客户端的详细文档。
您已经在使用Elasticsearch吗? 你有什么经验? 或者,也许您在阅读本文后会尝试一下。 在下面的评论中让我知道。
From: https://www.sitepoint.com/search-engine-node-elasticsearch/