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

这篇具有很好参考价值的文章主要介绍了Elasticsearch 8.X 如何依据 Nested 嵌套类型的某个字段进行排序?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、问题来源

这是来自社区的一个真实企业场景问题。

https://elasticsearch.cn/question/13135

如下所示, 希望在查出的结果后, 对结果进行后处理,对tags列表,根据depth进行排序。

{
"keyProperty":"22",
"name":"测试内容",
"_class":"com.xxxxxxxx.ElasticSearchContent",
"contentType":"attractionArea",
"content":"这是一条测试内容",
"timestamp":1701325254191,
"tags":[
{
"path":"33^^35^^36^^38",
"depth":4,
"id":38,
"label":"测试42"
},
{
"path":"33^^35^^36^^37^^39",
"depth":5,
"id":39,
"label":"测试51"
},
{
"path":"33^^35",
"depth":2,
"id":35,
"label":"测试22"
}
]
}

2、分析一下

Elasticsearch 能支持的排序方式罗列如下:

包含但不限于:

  1. 基于特定字段的排序

  2. 基于Nested对象字段的排序

  3. 基于特定脚本实现的排序

等等......

参见:

https://www.elastic.co/guide/en/elasticsearch/reference/current/sort-search-results.html#nested-sorting

再看咱们的开篇需求,

  • 第一:检索返回结果;

  • 第二:基于结果的 tags 数组下的子字段 depth 进行排序。

字段排序分类中的:基于特定字段的排序和基于 Nested 对象字段的排序,是对整个查询结果集进行排序,这在 Elasticsearch 中通常是针对顶层文档字段或者简单嵌套字段进行的。

而咱们开篇需求的应用场景和实现方式与之是不同的,哪咋办?

见招拆招了,只能考虑基于特定脚本实现的排序了。

Elasticsearch 8.X 如何依据 Nested 嵌套类型的某个字段进行排序?,elasticsearch,jenkins,大数据,搜索引擎,全文检索

要实现开篇的需求——即对每个文档的 tags 列表进行排序,需要在返回结果中对这些 tags 列表进行处理。

通常有两大类方案:

  • 使用脚本字段(script_fields)实现;

  • 在查询结果返回后在客户端进行处理,大白话:自己Java或Python程序层面处理。

3、尝试拆解实现

咱们要先模拟构造数据,包含创建索引和bulk 批量构造写入数据两个部分。

创建索引如下:

PUT /example_index
{
  "mappings": {
    "properties": {
      "keyProperty": {
        "type": "keyword"
      },
      "name": {
        "type": "text"
      },
      "_class": {
        "type": "keyword"
      },
      "contentType": {
        "type": "keyword"
      },
      "content": {
        "type": "text"
      },
      "timestamp": {
        "type": "date"
      },
      "tags": {
        "type": "nested",
        "properties": {
          "path": {
            "type": "keyword"
          },
          "depth": {
            "type": "integer"
          },
          "id": {
            "type": "integer"
          },
          "label": {
            "type": "text"
          }
        }
      }
    }
  }
}

导入数据:

POST /example_index/_bulk
{"index":{"_id":1}}
{"keyProperty":"22","name":"测试内容1","_class":"com.xxxxxxxx.ElasticSearchContent","contentType":"attractionArea","content":"这是一条测试内容","timestamp":1701325254191,"tags":[{"path":"33^^35^^36^^38","depth":4,"id":38,"label":"测试42"},{"path":"33^^35^^36^^37^^39","depth":5,"id":39,"label":"测试51"},{"path":"33^^35","depth":2,"id":35,"label":"测试22"}]}
{"index":{"_id":2}}
{"keyProperty":"23","name":"测试内容2","_class":"com.xxxxxxxx.ElasticSearchContent","contentType":"attractionArea","content":"这是另一条测试内容","timestamp":1701325254200,"tags":[{"path":"33^^35^^36","depth":5,"id":36,"label":"测试33"},{"path":"33^^35^^37","depth":3,"id":37,"label":"测试34"}]}

3.1 方案一:脚本字段(script_fields)实现自建排序

GET /example_index/_search
{
  "query": {
    "nested": {
      "path": "tags",
      "query": {
        "match_all": {}
      }
    }
  },
  "script_fields": {
    "sorted_tags": {
      "script": {
        "lang": "painless",
        "source": """
        if (!params._source.tags.empty) {
          def tags = new ArrayList(params._source.tags);
          boolean swapped;
          do {
            swapped = false;
            for (int i = 0; i < tags.size() - 1; i++) {
              if (tags[i].depth > tags[i + 1].depth) {
                def temp = tags[i];
                tags[i] = tags[i + 1];
                tags[i + 1] = temp;
                swapped = true;
              }
            }
          } while (swapped);
          return tags;
        } else {
          return null;
        }
      """
      }
    }
  }
}

召回结果如下:

Elasticsearch 8.X 如何依据 Nested 嵌套类型的某个字段进行排序?,elasticsearch,jenkins,大数据,搜索引擎,全文检索

有人可能会说,这不是扯吗?都整出个冒泡排序来了。

是的,就是传统的数组排序的脚本实现。当没有办法的时候,不考虑性能的时候,笨办法也是办法。

在 Elasticsearch 中处理大量数据时运行复杂的脚本可能会消耗较多的计算资源!

还有,冒泡排序是一种效率较低的排序算法,特别是对于大列表,其性能不是最佳的。

相比于使用 Elasticsearch 内置的排序功能,手动实现排序算法增加了脚本的复杂性。

3.2 方案二:脚本字段实现自建排序——lamda表达式排序

GET /example_index/_search
{
  "query": {
    "nested": {
      "path": "tags",
      "query": {
        "match_all": {}
      }
    }
  },
  "script_fields": {
    "sorted_tags": {
      "script": {
        "lang": "painless",
        "source": """
          if (!params._source.tags.empty) {
            def tags = new ArrayList(params._source.tags);
            tags.sort((a, b) -> a.depth.compareTo(b.depth));
            return tags;
          } else {
            return null;
          }
        """
      }
    }
  },
  "size": 10
}

这里使用了一个 lambda 表达式 (a, b) -> a.depth.compareTo(b.depth)。最后,返回排序后的 tags。

参见:

https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-fields.html

执行结果如下:

Elasticsearch 8.X 如何依据 Nested 嵌套类型的某个字段进行排序?,elasticsearch,jenkins,大数据,搜索引擎,全文检索

3.3 方案三:业务层面代码实现

啥意思,召回检索结果后,自己在内存里排序,想使用什么排序自便,按照自己习惯就可以。当然,Elastic中文社区创始人 、极限科技 CEO medcl 大佬也给出了他的网关方案:

写个 JS 脚本,通过极限网关,无缝的对查询结果进行改写就行了:

https://infinilabs.com/docs/latest/gateway/tutorial/path_rewrite_by_javascript/

这其实给复杂查询给了另一个更高维度升维的思考,值得借鉴。

Elasticsearch 8.X 如何依据 Nested 嵌套类型的某个字段进行排序?,elasticsearch,jenkins,大数据,搜索引擎,全文检索

4、小结

将问题展开,才能找到解决问题的方案。

当实现方案变得非常复杂,涉及性能问题时候,数据量少都没有问题;数据量大后,可以考虑找其他方案。

你如果也有类似困惑,欢迎交流。

推荐阅读

  1. 全网首发!从 0 到 1 Elasticsearch 8.X 通关视频

  2. 重磅 | 死磕 Elasticsearch 8.X 方法论认知清单

  3. 如何系统的学习 Elasticsearch ?

  4. 2023,做点事

  5. 干货 | Elasticsearch Nested 数组大小求解,一网打尽!

  6. Elasticsearch Nested 选型,先看这一篇!

  7. 干货 | 拆解一个 Elasticsearch Nested 类型复杂查询问题

  8. 干货 | Elasticsearch Nested类型深入详解

Elasticsearch 8.X 如何依据 Nested 嵌套类型的某个字段进行排序?,elasticsearch,jenkins,大数据,搜索引擎,全文检索

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

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

Elasticsearch 8.X 如何依据 Nested 嵌套类型的某个字段进行排序?,elasticsearch,jenkins,大数据,搜索引擎,全文检索

比同事抢先一步学习进阶干货!文章来源地址https://www.toymoban.com/news/detail-787088.html

到了这里,关于Elasticsearch 8.X 如何依据 Nested 嵌套类型的某个字段进行排序?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • clickhouse的嵌套数据结构Tuple、Array与Nested类型介绍和使用示例

    Tuple 是 ClickHouse 数据库中的一种数据类型,它允许在一个字段中存储由不同数据类型组成的元组(tuple)。 元组可以包含任意数量的值,并且每个值可以是不同的数据类型,如 int 、 float 、 string 、 date 等。 例如,以下是一个 clickhouse Tuple 类型的例子: (1, \\\'John\\\', 12.5, Date(\\\'2021-0

    2024年02月14日
    浏览(47)
  • es查询nested字段类型数组长度来判断是否包含多个值

    使用es时经常会碰到查询数组格式的字段是否有多个值的情况,总结一下。 一、字段类型为keywork时 当字段类型为keyword时(创建索引后,添加的第一条数据id字段格式为数组格式,便会导致后续的数据都是数组),查询id字段有多值时用以下查询语句: 二、字段类型为nested类型时

    2024年02月11日
    浏览(66)
  • Elasticsearch 复杂类型 Nested

    复杂类型 建模到底是个什么东东? 建模解决什么问题? 复杂类型的的检索问题 主要解决复杂类型无法搜索的问题 nested属于object类型的一种,是Elasticsearch中用于复杂类型对象数组的索引操作。Elasticsearch没有内部对象的概念,因此,ES在存储复杂类型的时候会把对象的 复杂层次

    2024年02月13日
    浏览(45)
  • ElasticSearch nested 字段多关键字搜索,高亮全部匹配关键字的处理

    ElasticSearch 版本号: 6.7.0 用户会传入多个去ES查询 ElasticSearch nested 字段 的多个字段,要求在返回的结果中被搜索的字段需要高亮所有匹配的。例如同时通过 上海 和 策划 ,再 工作经历 的列表中的 工作内容 和 公司名称 中搜索。如果有人员的 工作经历 中

    2024年04月22日
    浏览(59)
  • kibana中ES修改某个字段类型问题

     近日,发现同步数据到es的时候,有个新建的索引动态适配了mapping,而往往这种会有字段类型不是我们想要的,比如我这就有个tid字段,此字段要在聚合操作中使用,而此时的tid被识别成text类型了,而text不支持聚合,所以要更改字段类型为long或者keyword,注意es 不支持直接

    2024年02月08日
    浏览(52)
  • 深入了解ElasticSearch的Nested数据类型

    这个时候就需要用到nested,nested类型是object数据类型的特殊版本,它允许对象数组以一种可以相互独立查询的方式进行索引。 在Nested内部,每个对象索引其实是一个单独的隐藏文档,这意味着每个嵌套对象都可以独立于其他对象进行查询。 使用Nested需要先创建索引,依旧通

    2024年04月10日
    浏览(77)
  • Elasticsearch中object类型与nested类型以及数组之间的区别

    0、一般情况下用object 类型来查es中为json对象的字段数据,用nested来查es中为JsonArray数组类型的字段数据。 1、默认情况下ES会把JSON对象直接映射为object类型,只有手动设置才会映射为nested类型 2、object类型可以直接使用普通的逗号(.)查询,比如 3、nested类型的查询需要使用

    2024年01月22日
    浏览(84)
  • Elasticsearch按某个字段去重-实现group by效果

    已知es中存储了一张学生课程信息宽表,里边包含有student_name、student_id、teacher_id、课程信息等字段。 现在根据学生姓名或者班级ID,得出学生所在班级的所有授课教师信息。  既然是明细宽表,里边的教师的信息必然是有重复的,因此我们需要查询teacher_id的集合并去重,对

    2024年02月12日
    浏览(46)
  • Elasticsearch 基于 array 结构 的nested类型的索引的聚合查询

    这几天在做es的聚合查询,对那种一对多的产品数据查询的时候遇到了一些问题,做一下记录 针对每个产品名称[ product_name ]进行分组,并对预算[ budget ]求和 产品名称 预算 电视机 4000 手机 851 相机 5000 扑克牌 2 es查询语句==简化版 es查询的结果==简化版 注意电视机的doc_count为

    2024年02月16日
    浏览(59)
  • Elasticsearch索引之嵌套类型:深度剖析与实战应用

    码到三十五 : 个人主页 心中有诗画,指尖舞代码,目光览世界,步履越千山,人间尽值得 ! Elasticsearch是一个基于Lucene的搜索服务器,它提供了一个分布式、多租户能力的全文搜索引擎,并带有一个基于HTTP的Web界面和基于JSON的文档。在Elasticsearch中,嵌套类型索引是一个非常

    2024年04月09日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包