Elasticsearch 8.X 如何基于用户指定 ID 顺序召回数据?

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: Elasticsearch 8.X 如何基于用户指定 ID 顺序召回数据?

1、实战问题

如何根据输入的id 的顺序输出结果,id 个数有500个,还有分页?

问题来源:https://t.zsxq.com/0cdyq7tzr

2、方案探讨

2.1 Elasticsearch 默认排序机制

  • 在 Elasticsearch 中,如果未指定排序规则,检索结果的默认排序方式是按照文档的相关性得分(_score)进行降序排序。相关性得分表示了文档与查询的匹配程度。得分越高,文档与查询的匹配程度越高。
  • 有些情况下,查询结果的评分可能不相关或无法计算。例如,在过滤查询(如 term、terms 或 ids 查询)或布尔查询的 filter、must_not上下文中,Elasticsearch 不会计算评分。在这些情况下,文档的评分通常为 1.0 或其他默认值(filter、must_not 评分为0)。

2.2 如何基于用于指定的 ID 顺序召回数据?

原生的 Elasticsearch 检索机制没有这个功能。那就意味着,咱们得自己实现。

如何实现呢?把用户给定的序列(非递增也非递减的无规律序列,如3、1、5、7),看成一维数组数据。

他们的数组的下标只能是0、1、2、3.....也就是说,下标是有序的。

那么接下来问题就转嫁为如何基于数组下标进行升序排序的问题?

借助 sort 排序的 script 脚步排序即可实现。

3、前置条件

PUT /_cluster/settings
{
  "transient": {
    "indices.id_field_data.enabled": true
  }
}

解读如下:

PUT /_cluster/settings 请求是 Elasticsearch 中用于更新集群设置的 API。这个特定请求的含义是,我们要更新集群的临时(transient)设置。

{"transient": {"indices.id_field_data.enabled": true}}

在这个请求中,我们设置了 indices.id_field_data.enabled 为 true。

这个设置用于控制 Elasticsearch 是否允许对 _id 字段进行 fielddata 访问。

默认情况下,这个设置是禁用的(false),因为访问 _id 字段的 fielddata 可能会消耗大量内存,并可能导致性能下降。

这里使用的 transient 属性意味着设置的更改是临时的,只在集群重启之前有效。当集群重新启动时,这个设置会被重置为默认值。如果您希望永久更改此设置,可以使用 persistent 属性:

PUT /_cluster/settings
{"persistent": {"indices.id_field_data.enabled": true}}

请注意,在实际应用中,我们通常不建议启用 _id 字段的 fielddata 访问,因为它可能会导致性能问题。

4、给出样例数据

给出批量数据,以备后用!

PUT test_index/_bulk
{"index":{"_id":1}}
{"title":"001"}
{"index":{"_id":3}}
{"title":"003"}
{"index":{"_id":5}}
{"title":"005"}
{"index":{"_id":7}}
{"title":"007"}

5、给出实现

POST test_index/_search
{
  "query": {
    "ids": {
      "values": [
        "3",
        "1",
        "5",
        "7"
      ]
    }
  },
  "sort": [
    {
      "_script": {
        "type": "number",
        "script": {
          "lang": "painless",
          "source": """
          List ids_list = params.ids;
          String cur_id = doc['_id'].value;
          for(int i = 0; i < ids_list.length; i++)
          {
            if(cur_id.equals(ids_list[i]))
            {
              return i;
            }
          }
          return -1;
          """,
          "params": {
            "ids": ["3","1","5","7"]
          }
        },
        "order": "asc"
      }
    }
  ]
}

实现解读:

这个 Elasticsearch 查询用于从名为 test_index 的索引中搜索文档。查询的主要目的是根据给定的 ID 列表检索文档,并按照 ID 列表的顺序对检索到的文档进行排序。

以下是查询的各个部分的详细解释:

  • size: 设置为 10,表示查询将返回最多 10 个文档。在这种情况下,由于我们的 ID 列表只包含 4 个 ID,因此查询将返回最多 4 个文档。
  • query: 使用 ids 查询来筛选给定 ID 列表中的文档。在这个例子中,我们要检索 ID 为 "3"、"1"、"5" 和 "7" 的文档。
  • sort: 使用脚本排序(_script)按照给定的 ID 列表的顺序对返回的文档进行排序。-- type: 设置为 "number",表示脚本返回的值将被视为数字。
  • script: 定义了一个 Painless 脚本,用于计算每个文档的排序值。
  • lang: 设置为 "painless",表示脚本使用 Painless 语言编写。
  • source: 脚本的源代码。这个脚本遍历给定的 ID 列表,查找与当前文档 _id 匹配的 ID。如果找到匹配项,则返回匹配项在 ID 列表中的索引作为排序值。如果没有找到匹配项,返回 -1(在这个例子中,实际上不会发生)。
  • params: 脚本的参数,包含一个名为 ids 的列表,其中包含了要排序的 ID。这里,我们将 ID 列表作为参数传递给脚本。
  • order: 设置为 "asc",表示按升序对文档进行排序。这意味着查询结果将按照 ID 列表的顺序返回。

通过这个查询,您可以从 test_index 索引中获取指定 ID 的文档,并按照给定的 ID 顺序("3"、"1"、"5"、"7")对结果进行排序。

6、小结

关于分页,参考普通检索实现即可。

本文结合脚本排序的方式实现了基于用户指定顺序召回结果数据。视频解读如下:

大家有没有更好的实现方式呢?欢迎留言交流。

推荐阅读


更短时间更快习得更多干货!

和全球 近1900+ Elastic 爱好者一起精进!

比同事抢先一步学习进阶干货!


相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
5月前
|
API 网络架构 索引
Elasticsearch索引中数据的增删改查与并发控制
Elasticsearch索引中数据的增删改查与并发控制
|
5月前
|
存储 监控 数据挖掘
使用 Meltano 将数据从 Snowflake 导入到 Elasticsearch:开发者之旅
【6月更文挑战第9天】Meltano,一个开源数据集成框架,简化了从Snowflake到Elasticsearch的数据迁移。这个工具支持多种数据源,提供易于配置的界面。要开始,需安装Meltano并配置连接信息。一个简单的YAML示例展示了如何定义从Snowflake到Elasticsearch的迁移任务。Meltano自动执行迁移,同时提供监控和日志功能。借助Meltano,用户能高效集成数据,提升搜索和分析能力,适应不断增长的数据需求和挑战。
99 6
|
1月前
|
Web App开发 JavaScript Java
elasticsearch学习五:springboot整合 rest 操作elasticsearch的 实际案例操作,编写搜索的前后端,爬取京东数据到elasticsearch中。
这篇文章是关于如何使用Spring Boot整合Elasticsearch,并通过REST客户端操作Elasticsearch,实现一个简单的搜索前后端,以及如何爬取京东数据到Elasticsearch的案例教程。
185 0
elasticsearch学习五:springboot整合 rest 操作elasticsearch的 实际案例操作,编写搜索的前后端,爬取京东数据到elasticsearch中。
|
1月前
|
消息中间件 监控 关系型数据库
MySQL数据实时同步到Elasticsearch:技术深度解析与实践分享
在当今的数据驱动时代,实时数据同步成为许多应用系统的核心需求之一。MySQL作为关系型数据库的代表,以其强大的事务处理能力和数据完整性保障,广泛应用于各种业务场景中。然而,随着数据量的增长和查询复杂度的提升,单一依赖MySQL进行高效的数据检索和分析变得日益困难。这时,Elasticsearch(简称ES)以其卓越的搜索性能、灵活的数据模式以及强大的可扩展性,成为处理复杂查询需求的理想选择。本文将深入探讨MySQL数据实时同步到Elasticsearch的技术实现与最佳实践。
93 0
|
3月前
|
存储 缓存 监控
|
3月前
|
数据采集 人工智能 自然语言处理
阿里云Elasticsearch AI语义搜索:解锁未来搜索新纪元,精准洞察数据背后的故事!
【8月更文挑战第2天】阿里云Elasticsearch AI场景语义搜索最佳实践
204 5
|
3月前
|
存储 搜索推荐 API
探究:Elasticsearch 文档的 _id 是 Lucene 的 docid 吗?
【8月更文挑战第31天】在深入探索Elasticsearch(简称ES)这一强大的搜索引擎时,了解其底层存储机制——特别是与Lucene的关系,对于优化查询性能、设计高效的数据模型至关重要。其中,一个常见且容易引发误解的问题便是:Elasticsearch中文档的_id字段是否直接等同于Lucene的docid?本文将通过图文并茂的方式,详细剖析这一问题,帮助读者理解两者之间的微妙关系。
86 0
|
3月前
|
自然语言处理 Java 关系型数据库
ElasticSearch 实现分词全文检索 - id、ids、prefix、fuzzy、wildcard、range、regexp 查询
ElasticSearch 实现分词全文检索 - id、ids、prefix、fuzzy、wildcard、range、regexp 查询
103 0
|
4月前
|
存储 安全 文件存储
【elasticsearch】es6重启服务后数据消失,es6如何配置数据持久化储存
【elasticsearch】es6重启服务后数据消失,es6如何配置数据持久化储存
53 1
|
5月前
|
索引
利用滚动索引来管理海量Elasticsearch数据
利用滚动索引来管理海量Elasticsearch数据
104 3