百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

来自钉钉群的问题——Elasticsearch 如何实现文件名自定义排序

toyiye 2024-06-21 11:57 11 浏览 0 评论

1、背景

在数字时代,图像数据的管理已成为数据架构的一部分。然而,随之而来的挑战是如何有效地索引和检索这些图像文件。

这不仅涉及存储,更重要的是如何根据特定的属性(如文件名中的数字)进行排序,以便用户可以按照预期的顺序查看图像。

如下问题来自Elastic 钉钉技术交流群:

2、解决方案探讨

在Elasticsearch中,我们经常面对需要对数据进行排序的需求。单就排序,咱们之前有过几篇文章分析不同业务场景的排序实现。

1、Elasticsearch 8.X 如何依据 Nested 嵌套类型的某个字段进行排序?

2、Elasticsearch 线上问题排查——搞一天了,明天还要给客户解决这个问题

3、Elasticsearch 8.X:这个复杂的检索需求如何实现?

4、近期,几个典型 Elasticsearch 8.X 问题及方案探讨

5、最近几个典型 Elasticsearch 线上易出错难排查问题汇集,咱们得避免!

6、Elasticsearch 线上实战问题及解决方案探讨

仅就上图中的文件名进行排序,会怎么样呢?我们构造一下数据,执行一下看。

用默认动态Mapping 结构,批量写入数据。

POST /my_photos/_bulk
{ "index" : { "_id" : "1" } }
{ "photo_id" : "photo1.jpg", "upload_date" : "2024-02-01T10:00:00" }
{ "index" : { "_id" : "2" } }
{ "photo_id" : "photo2.jpg", "upload_date" : "2024-02-01T10:05:00" }
{ "index" : { "_id" : "3" } }
{ "photo_id" : "photo12.jpg", "upload_date" : "2024-02-01T10:10:00" }
{ "index" : { "_id" : "4" } }
{ "photo_id" : "photo111.jpg", "upload_date" : "2024-02-01T10:15:00" }


### 执行检索
GET /my_photos/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "photo_id.keyword": {
        "order": "asc"
      }
    }
  ]
}

召回结果,同图中后半部分结果一致。

结果并没有达到预期。

而可行的解决方案,还得从文件名入手才可以。图像文件名包含数字,需要根据这些数字进行排序,这才是根本!

3、解决方案实现

我们采用两种不同的解决方案来尝试解决这个问题。

第一种:基于脚本排序。

第二种:复杂问题简单化,预处理管道拆分出数值字段,基于数值排序。

3.1 方案1:脚本排序实现

使用 _script 进行排序是一种灵活的方法,它允许我们编写自定义脚本来解析文件名并提取排序依据的数字。

GET /my_photos/_search
{
  "query": {
    "match_all": {}
  },
  "sort": {
    "_script": {
      "type": "number",
      "script": {
        "lang": "painless",
        "source": """
          String photoId = doc['photo_id.keyword'].value;
          if (photoId == null) return 0;
          Matcher m = /[0-9]+/.matcher(photoId);
          if (m.find()) {
            return Integer.parseInt(m.group(0));
          } else {
            return 0;
          }
        """
      },
      "order": "asc"
    }
  }
}

执行结果已经有序:

上述脚本基于正则表达式从photo_id字段中查找并提取出数字,如果找到就返回这个数字,如果找不到就返回0。

这样的操作对于根据数字对文档进行排序非常有用。

虽然这种方法非常强大,但它可能会因为脚本的执行而影响查询性能,数据量巨大的时候,咱们要慎用!

3.2 方案2:预处理解决方案实现

除了上面的方案,另一种方法是在索引数据时使用Ingest管道预处理图像文件名。

这样可以在数据索引时就提取出文件名中的数字并存储在一个专门的字段中。

这种方法的好处是可以显著提高排序的效率,因为数字已经被预处理并作为数值类型存储,使得排序操作更加快速。

就是开头咱们提到的复杂问题简单化。

创建预处理管道,基于 grok 提取数值字段

PUT _ingest/pipeline/extract_photo_number
{
  "description": "Extracts numbers from photo_id and stores it in photo_number",
  "processors": [
    {
      "grok": {
        "field": "photo_id",
        "patterns": ["%{NUMBER:photo_number:int}"]
      }
    }
  ]
}

DELETE my_photos_20240201

### 创建索引的时候,记得指定上面创建好的预处理管道。
### 新增的字段photo_number,和上面的预处理管道获取的字段一一对应。
PUT my_photos_20240201
{
  "settings": {
    "default_pipeline":"extract_photo_number"
  }, 
  "mappings": {
    "properties": {
      "photo_id": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "photo_number": {
        "type": "long"
      },
      "upload_date": {
        "type": "date"
      }
    }
  }
}

### 批量写入数据
POST /my_photos_20240201/_bulk
{ "index" : { "_id" : "1" } }
{ "photo_id" : "photo1.jpg", "upload_date" : "2024-02-01T10:00:00" }
{ "index" : { "_id" : "2" } }
{ "photo_id" : "photo2.jpg", "upload_date" : "2024-02-01T10:05:00" }
{ "index" : { "_id" : "3" } }
{ "photo_id" : "photo12.jpg", "upload_date" : "2024-02-01T10:10:00" }
{ "index" : { "_id" : "4" } }
{ "photo_id" : "photo111.jpg", "upload_date" : "2024-02-01T10:15:00" }

### 执行检索和排序
POST my_photos_20240201/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "photo_number": {
        "order": "asc"
      }
    }
  ]
}

官方文档参考:

https://www.elastic.co/guide/en/elasticsearch/reference/current/grok-processor.html

执行结果如下:

与脚本排序对比可以看出:

  • 预处理方案数据的处理逻辑前移,发生在数据索引的阶段,而非查询阶段;
  • 查询时可以直接依据数值类型的 photo_number字段进行快速排序,无需在查询时动态解析文本字段,从而提高了查询性能,并减少了对资源的消耗。
  • 还提升了数据结构的清晰度和索引的整体效率

4、小结

本文探讨了在Elasticsearch中对包含数字的图像文件名进行排序的挑战及其解决方案。

在选择哪种方案时,我们需要考虑实际需求和系统资源。

如果对性能有较高要求,预处理方案更为合适。但如果需求复杂多变,可能需要脚本排序的灵活性。

我更想跟大家探讨的是:未来的数据建模应考虑到数据的索引和查询模式。

例如,如果我们知道将来需要按照文件名中的数字排序,那么在设计数据模型时就应该考虑到这一点,以便于实现高效的查询。

前置考虑得越充分,后面就越省事!


作者:铭毅天下

来源:微信公众号:铭毅天下Elasticsearch

出处:https://mp.weixin.qq.com/s/mjmXFkNflWxzqALg1kSaQw

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码