如果你问十个不同的开发人员这个问题“什么是 Elasticsearch?” 如果他们每个人都有不同的答案,请不要感到惊讶。他们都没有错;当然,只是 Elasticsearh 如此多才多艺。这种多功能性使 Elasticsearch 作为许多编程问题的解决方案越来越受欢迎。
Node如何使用Elasticsearch?如果你一直想尝试这项技术但还没有机会,那么今天,在本教程中,我们将向你介绍 Elasticsearch 的基本概念。然后,我们将使用它使用 Node.js 构建一个简单的搜索引擎,包括详细的Node Elasticsearch用法示例。
什么是弹性搜索?
这是一个可以有十种不同答案的问题。如果我必须将所有这些压缩到一个语句中,我可以说,Elasticsearch 是一个可分发的、开源的、分析和搜索引擎。
Elasticsearch 建立在 Apache Lucene 之上。它将数据以 JSON 格式存储在基于文档的结构中。在这方面,它类似于 MongoDB 之类的 NoSQL 数据库。
你可以使用 Elasticseach 近乎实时地存储和搜索大量数据。它还提供了用于执行存储和搜索操作的 REST API。Elasticsearch 具有高度可扩展性,其分布式后端允许跨节点集群分发任务,包括搜索、索引和分析。
为了更好地理解它在内部是如何工作的,让我们来看看 Elasticsearch 使用的一些核心组件和概念。
集群
集群类似于我们在分布式系统中看到的任何其他集群。它是节点的集合,这些节点是单独的 Elasticsearch 服务器。
节点
Node 是 Elasticsearch 的一个实例,你可以在其中存储、索引和搜索数据。节点可以属于多种类型。
每个集群都有一个主节点,负责集群范围的管理和配置。集群中的数据节点负责处理数据,例如执行 CRUD 操作以及响应搜索和数据聚合查询。
你可以查询集群中的每个节点,但某些称为客户端节点的节点会将接收到的请求转发到主节点或数据节点,而不会自行处理它们。
文档
文档是节点可以索引的基本信息单元。文档中的数据以 JSON 格式存储。例如,如果你正在构建一个电子商务网站,你可以将每个产品的详细信息存储在不同的文档中。数据可以是不同的类型,从数字到文本再到日期。
指数
Elasticsearch 中索引的概念与 MySQL 等数据库不同。
在 Elasticsearch 中,索引是具有相似特征的文档的集合。例如,在以前的电子商务网站中,你可以创建产品索引,其中包含所有单独的产品文档。
每个索引都有一个唯一的名称。你可以在对其文档执行 CRUD 或搜索操作时使用此名称。它也是你可以在 Elasticsearch 中查询的最高级别的实体。
分片和副本
你可以将单个索引分成多个部分,这些部分称为分片。每个分片都表现为一个功能齐全且独立的“索引”。你可以将索引的分片分布在多个节点上,确保存储在单个节点中的数据不会超出其容量。
你可以通过创建分片的“副本”来保护系统免受节点故障的影响,这可能会导致单个分片无法访问。它们是存储在节点集群中的分片的冗余副本。副本也有助于扩展集群的查询容量。
倒排索引
Elasticsearch 使用倒排索引的概念来提供快速的全文搜索结果。倒排索引是一种类似于哈希图的数据结构,因为它将单个单词映射到它们的位置。大多数搜索引擎使用它在查询大型数据集时提供快速结果。
在 Elasticsearch 中,倒排索引识别出现在索引中文档文本字段内的每个唯一单词,并将它们与每个单词出现的所有文档的位置进行映射。
现在,当全文搜索查询发送到 Elasticsearch 时,尽管数据集很大,但它会在几毫秒内使用倒排索引过滤搜索查询中出现的每个单词的文档。
例如,让我们考虑包含两个不同文本的两个文档:“programming is forprograms”和“programmers are awesome”。
如果这两个是我们索引中仅有的文档,那么 Elasticsearch 创建的倒排索引将类似于此。
Word | Document 1 | Document 2 |
---|---|---|
programming | true | false |
is | true | false |
for | true | false |
programmers | true | true |
are | false | true |
awesome | false | true |
请注意,实际倒排索引存储的信息比上表中包含的信息多。
映射
该映射为文档中存储的每个数据单元定义了一个(或多个)字段类型。就像我之前提到的,Elasticsearch 存储属于不同字段类型的数据 。
但是,你可以选择不最初定义字段类型。Elasticsearch 有一个称为动态映射的功能,它会自动检测新字段并将其添加到索引中。
对于属于不同字段类型的数据,Elasticsearch 索引的工作方式不同。例如,文本字段存储在倒排索引中,而数字和地理字段存储在 BKD 树中。
你还可以为一个数据单元定义多个字段类型。例如,你可以给出字符串“文本”和“关键字”字段类型。然后,该字符串将被索引为文本字段和关键字字段。这很重要,因为现在我们可以轻松地在全文搜索中搜索该字符串,并将其用作关键字进行聚合和排序。
Elasticsearch 在哪里使用?
Elasticsearch 是一种用于许多用例的技术。让我们来看看其中的一些。
- 网站搜索:一些网站需要提供快速搜索功能。例如,在电子商务网站中,用户应该能够快速搜索产品并获得结果。我们可以实现此功能,包括使用 Elasticsearch 自动完成等附加功能。
- 日志记录和日志分析:Elasticsearch 用于实时存储和分析来自 Web 应用程序和其他类似应用程序的日志。
- 更多的分析用途:我们还可以将 Elasticsearch 用于更多分析任务,例如安全分析和业务分析。Elasticsearch stack 提供了有用的工具,比如 Kibana,用于数据可视化和管理,可以轻松完成这项任务。
- 系统监控和基础设施指标:同样,Elasticsearch 用于收集、存储和处理来自不同系统的性能指标并实时可视化它们。
使用 Elasticsearch 和 Node 构建搜索引擎
Node如何使用Elasticsearch?经过几分钟的阅读使你的眼睛流血,现在你已经到了有趣的部分。我们将实现一个简单的 Node API 来与 Elasticsearch 交互。在本教程中,我们将创建端点以创建新记录和搜索存储的数据。
首先,请确保按照本指南在你的设备上安装 Elasticsearch 。安装后,启动 Elasticsearch 并通过向 Elasticsearch 服务器发送请求来确保它正常工作。
curl http://127.0.0.1:9200
然后,为本教程设置一个新的 Node 项目。
Node Elasticsearch用法示例:我们使用名为elasticsearch的 Node Elasticsearch 客户端模块。因此,请确保将软件包与 express 和 body-parser 一起安装。
npm install elasticsearch express body-parser
在app.js
我们项目的文件中,像往常一样设置 Node 服务器。
const express = require("express")
const bodyParser = require("body-parser")
const elasticsearch = require("elasticsearch")
const app = express()
app.use(bodyParser.json())
app.listen(process.env.PORT || 3000, () => {
console.log("connected")
})
现在,初始设置已完成。我们可以通过创建一个 Elasticsearch 客户端来开始使用 Elasticsearch。
const esClient = elasticsearch.Client({
host: "http://127.0.0.1:9200",
})
接下来,我们将创建 POST/products
端点。它接受 POST 请求以将新产品索引products
到 Elasticsearch 中调用的索引中。
为此,我们可以使用 elasticsearch 模块中的 index 方法。
app.post("/products", (req, res) => {
esClient.index({
index: 'products',
body: {
"id": req.body.id,
"name": req.body.name,
"price": req.body.price,
"description": req.body.description,
}
})
.then(response => {
return res.json({"message": "Indexing successful"})
})
.catch(err => {
return res.status(500).json({"message": "Error"})
})
})
Node Elasticsearch构建搜索引擎示例:由于在我们第一次启动服务器时索引“products”并不存在,因此对该端点的第一个请求将提示 Elasticsearch 创建新索引。
我们可以通过 Postman 发送一个新的请求来测试这条路由。如果你的应用程序正常运行,你将看到响应消息“索引成功”。
我已经索引了几个产品,其中包含 iPhone 和 Apple 之类的词。由于我们想了解 Elasticsearch 如何响应全文查询,我建议你也将一些名称相似的产品编入索引。
接下来,让我们创建 GET/products
端点。它通过文本查询处理用户正在搜索的产品的 GET 请求。我们使用此文本查询来搜索在 Elasticsearch 中索引的产品的名称字段,以便服务器可以响应与用户正在查找的产品相似的产品列表。
app.get("/products", (req, res) => {
const searchText = req.query.text
esClient.search({
index: "products",
body: {
query: {
match: {"name": searchText.trim()}
}
}
})
.then(response => {
return res.json(response)
})
.catch(err => {
return res.status(500).json({"message": "Error"})
})
})
Node Elasticsearch用法示例:同样,我们可以通过 Postman 发送请求来测试这条路由。由于我保存了名称为 Apple 和 iPhone 等产品的列表,因此我使用了包含其中一个词的搜索词。我使用的搜索词是“blue iphone backcover”。
服务器响应两种产品,一种是“Apple iPhone 11 backcover”,另一种是“Apple iPhone 11”。
尽管第二个结果不是用户想要的,但 Elasticsearch 将其视为命中,因为它与搜索查询中的一个词“iphone”相匹配。但它列在与我们的查询更相关的结果之后。
如果再次查看返回的结果,你会看到每次命中都会返回一个名为 score 的字段。它确定结果与搜索查询的相关性。得分越高表示相关性越高,命中按得分的降序排列,因此最佳匹配显示在顶部。
Node Elasticsearch构建搜索引擎示例结论
Node如何使用Elasticsearch?正如你在本教程后发现的那样,Elasticsearch 是一个非常有趣的工具。Elasticsearch 的功能远不止我在此介绍的内容。但我希望本教程足以说服你在下一个项目中尝试一下。所以,尽情享受 Elasticsearch 吧。