Elasticsearch 中两个非常重要的概念是文档和索引。
文档是字段及其相关值的集合。要使用 Elasticsearch,您必须将数据整理成文档,然后将所有文档添加到索引中。你可以把索引看作是以高度优化的格式存储的文件集合,旨在执行高效搜索。
如果您使用过其他数据库,您可能会知道许多数据库都需要一个模式定义,这基本上是对要存储的所有字段及其类型的描述。Elasticsearch 索引可以根据需要配置模式,也可以从数据本身自动导出模式。在本节中,您将让 Elasticsearch 自行找出模式,这对于文本、数字和日期等简单数据类型非常有效。稍后,在介绍了更复杂的数据类型后,您将学习如何提供显式模式定义。
创建索引
这就是使用 Python 客户端库创建 Elasticsearch 索引的方法:
在本例中,self.es 是Elasticsearch 类的实例,在本教程中,该实例存储在search.py 中的Search 类中。Elasticsearch 部署可用于存储多个索引,每个索引由一个名称标识,如上面例子中的my_documents 。
还可以删除索引:
如果尝试创建的索引名称已分配给现有索引,则会出现错误。有时,创建索引时,如果存在索引的前一个实例,则自动删除该实例是非常有用的。这在开发应用程序时尤其有用,因为您可能需要多次重新生成索引。
让我们在search.py 中添加一个create_index() 辅助方法。在代码编辑器中打开该文件,在底部添加以下代码,保持现有内容不变:
create_index() 方法首先删除名称为my_documents 的索引。ignore_unavailable=True 选项可防止在找不到索引名称时调用失败。该方法中的下一行将创建一个全新的索引,并使用相同的名称。
本教程中的示例应用程序需要一个 Elasticsearch 索引,因此它将索引名称硬编码为my_documents 。对于使用多个索引的更复杂应用程序,可以考虑将索引名称作为参数。
将文件添加到索引
在 Python 的 Elasticsearch 客户端库中,文档表示为键/值字段的字典。具有字符串值的字段会自动编入索引,以便进行全文和关键字搜索,但除了字符串外,您还可以使用数字、日期和布尔等其他字段类型,这些字段也会编入索引,以便进行过滤等高效操作。您还可以构建复杂的数据结构,将字段设置为包含子项的列表或字典。
要将文档插入索引,需要使用 Elasticsearch 客户端的index() 方法。例如
index() 方法的返回值是 Elasticsearch 服务返回的响应。此响应中返回的最重要信息是一个键名为_id 的项,代表文档插入索引时分配给它的唯一标识符。该标识符可用于检索、删除或更新文件。
既然知道了如何插入文档,让我们继续在search.py 中建立一个有用的助手库、Search 的insert_document() 方法。在search.py 的底部添加此方法:
该方法接受来自调用者的 Elasticsearch 客户端和文档,并将文档插入my_documents 索引,返回服务的响应。
注意:本教程不涉及这些操作,但 Elasticsearch 客户端也可以修改和删除文档。请参阅 Python 库文档中的Elasticsearch 类参考,了解所有可用的操作。
从 JSON 文件摄入文件
在建立新的 Elasticsearch 索引时,您可能需要导入大量文件。在本教程中,启动项目包括一个data.json文件,其中包含一些 JSON 格式的数据。在本节中,您将学习如何将该文件中包含的所有文件导入索引。
包含在data.json中的文件结构如下:
name文件标题url:外部网站托管文件的 URLsummary文件内容简介content:文件正文created_on创建日期updated_at:更新日期(如果文件从未更新,则可能缺失)category文件类别:文件的类别,可以是github、sharepoint或teamsrolePermissions:角色权限列表
此时,我们建议您在编辑器中打开data.json,以熟悉将要处理的数据。
从本质上讲,导入大量文件与在 for 循环中导入一个文件没有区别。要导入data.json文件的全部内容,可以这样做:
虽然这种方法行之有效,但却不能很好地扩展。如果要插入大量文件,就需要调用 Elasticsearch 服务的次数。遗憾的是,每次 API 调用都会产生性能成本,而且服务还设置了费率限制,无法快速进行大量调用。因此,最好使用 Elasticsearch 服务的批量插入功能,该功能允许在单个 API 调用中向服务传达多个操作。
insert_documents() 方法,并将其添加到search.py 的底部、使用bulk() 方法在一次调用中插入所有文件:
该方法接受一个文件列表。它没有单独添加每个文档,而是将其组合成一个名为operations 的列表,然后将该列表传递给bulk() 方法。每份文件都有两个条目被添加到operations 列表中:
- 说明要执行的操作,设置为
index,索引名称作为参数给出。 - 文件的实际数据
处理批量请求时,Elasticsearch 服务会从头开始遍历操作列表,并执行所请求的操作。
重新生成索引
在学习本教程时,您需要多次重新生成索引。为简化这一操作,请在search.py 中添加reindex() 方法:
该方法结合了之前创建的create_index() 和insert_documents() 方法,因此只需一次调用就能销毁旧索引(如果存在),并建立和重新填充新索引。
注意:在为大量文件编制索引时,最好将文件列表分成较小的文件集,然后分别导入每个文件集。
为了更方便地调用该方法,让我们通过flask 命令来公开它。在代码编辑器中打开app.py,在底部添加以下函数:
@app.cli.command() 装饰器告诉 Flask 框架将此函数注册为自定义命令,该命令将以flask reindex 的形式提供。命令名称取自函数名称,此处包含 docstring 是因为 Flask 在--help 文档中使用了它。
reindex() 函数的响应又是 Elasticsearch 客户端bulk() 方法的响应,其中包含一些有用的项目,可用于构建漂亮的状态信息。其中,response['took'] 是以毫秒为单位的调用持续时间,response['items'] 是每个操作的单个结果列表,实际上并不直接有用,但该列表的长度提供了插入文件的计数。
在终端会话中运行flask --help ,确保 Python 虚拟环境已激活(如果终端会话仍在运行 Flask 应用程序,可以打开第二个终端窗口),看看效果如何。在帮助屏幕的末尾,你会看到reindex 选项与 Flask 框架提供的其他选项一起作为可用命令出现:
现在,当你想生成一个干净的索引时,只需运行flask reindex 。
下一个
搜索基础知识