当前位置:   article > 正文

详细教程:elasticsearch基于script统计索引中某字段(keyword或者text类型)的字符串长度_elasticsearch script

elasticsearch script

目录

1.需求场景

2.实现方案

2.1 keyword类型

2.2 text类型

设置fielddata=true

reindex把text文本改keyword

3.参考资料


1.需求场景

统计es索引中某字段的字符串长度有多种使用场景,例如:

1.想统计出索引文本内容分别在300字内、500字内、1000字内的文章数量;

2.将查询结果按某字段的字符串长度排序;

3.想实验过滤短文本后的查询效果 ......

2.实现方案

elasticsearch 5.0及之后的版本中存储字符串的类型有两种,keyword和text。

text属性的字段在es中存储时,会被自动分词存储,因此text属性的字段支持分词,但不支持 过滤、排序和聚合等操作。keyword属性的字段更方便统计,但通常情况下,对于存储文本内 容的content我们在设置索引mapping的时候都会将其设为text,这一设置方便了我们进行关键 词的分词全文检索,但当想要对text类型字段进行聚合等相关统计操作时带来不便。

下面针对两种类型分别介绍基于script统计字符串长度的步骤

2.1 keyword类型

  1. #查找标签长度小于5
  2. GET wendongmi_read/_search
  3. {
  4. "query": {
  5. "bool": {
  6. "filter": [
  7. {
  8. "script": {
  9. "script": {
  10. "source": """
  11. if (doc['_tags'].size() !=0) {
  12. doc['_tags'].value.length() < 5
  13. }
  14. """,
  15. "lang": "painless"
  16. }
  17. }
  18. }
  19. ]
  20. }
  21. },
  22. "track_total_hits": true,
  23. "size": 10
  24. }

因为keyword类型本身便可进行聚合、过滤、排序等,可以直接使用 doc['field_name'].valu e.length() 的语法获取该属性值的长度进行相关过滤统计。

2.2 text类型

当尝试直接对text类型字段使用如keyword类型一样的语法时,会出现如下报错:

Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [Art_Content] in order to load field data by uninverting the inverted index. Note that this can use significant memory.

针对text类型,其实es官方报错的提示语已经给如何对text类型做统计指明了两个方向。

进行fielddata=true设 置或者把该字段变成keyword类型 

设置fielddata=true
  1. POST test_read/_mapping
  2. {
  3. "properties":{
  4. "content": {
  5. "type" : "text",
  6. "fielddata": false
  7. }
  8. }
  9. }

在es中,text类型的字段使用一种叫做fielddata的查询时内存数据结构。当字段被排序,聚合 或者通过脚本访问时这种数据结构会被创建。它是通过从磁盘读取每个段的整个反向索引来构 建的,然后存存储在java的堆内存中。

fileddata默认是不开启的。fileddata可能会消耗大量的堆空间,尤其是在加载高基数文本字段 时。一旦fielddata已加载到堆中,它将在该段的生命周期内保留。此外,加载fielddata是一个 昂贵的过程,可能会导致用户遇到延迟命中。这就是默认情况下禁用fielddata的原因。不推荐在生产环境使用

设置后,即可使用script统计成功(ps:速度很慢)

  1. GET test_read/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "filter": [
  6. {
  7. "script": {
  8. "script": {
  9. "source": """
  10. if (doc['content'].size() !=0) {
  11. doc['content'].value.length() < 5
  12. }
  13. """,
  14. "lang": "painless"
  15. }
  16. }
  17. }
  18. ]
  19. }
  20. },
  21. "track_total_hits": true,
  22. "size": 10
  23. }
reindex把text文本改keyword

如果是暂时统计一下获取某个数据的话(比如资讯文章里文本300字内的文章数)可以新设置一个专用于统计的索引,将要统计的字段设为keyword,将需要统计的数据reindex到该索引

这里需要注意的是,ES5.X版本以后,keyword支持的最大长度为32766个UTF-8字符。如果待统计的本文较长,直接reindex会因为长度超过keyword支持的最大长度而报错,这时需要设置ignore_above,设置ignore_above后,超过给定长度后的数据将不被索引,无法通过term精确匹配检索返回结果。

  1. PUT test_stat
  2. {
  3. "aliases": {
  4. "test_stat_read": {},
  5. "test_stat_write": {}
  6. },
  7. "mappings": {
  8. "properties": {
  9. "type" : {
  10. "type" : "keyword"
  11. },
  12. "content" : {
  13. "type": "text",
  14. "fields": {
  15. "keyword": {
  16. "type": "keyword",
  17. "ignore_above": 3000
  18. }
  19. }
  20. },
  21. "title" : {
  22. "type" : "keyword"
  23. }
  24. }
  25. },
  26. "settings": {
  27. "index": {
  28. "refresh_interval": "1s",
  29. "number_of_shards": "1",
  30. "number_of_replicas": "0"
  31. }
  32. }
  33. }

设置后,即可通过以下脚本进行统计

  1. #查找content长度大于1000
  2. GET test_stat/_search
  3. {
  4. "query": {
  5. "bool": {
  6. "filter": [
  7. {
  8. "script": {
  9. "script": {
  10. "source": """
  11. if (doc['content.keyword'].size() !=0) {
  12. doc['content.keyword'].value.length() > 1000
  13. }
  14. """,
  15. "lang": "painless"
  16. }
  17. }
  18. }
  19. ]
  20. }
  21. },
  22. "track_total_hits": true,
  23. "size": 0
  24. }

语法总结

  • type为text时,我们可以通过doc['field_name'].length或者doc['field_name'].size()获取该属性对应数组的长度;

  • type为keyword时,则使用doc['field_name'].value.length()获取属性值的长度,但是需要注意,如果doc['field_name'].value的值存在为null的情况,因此需要使用doc['field_name'].size()优先判空。

3.参考资料

[Text type family | Elasticsearch Guide [8.8] | Elastic]

Text type family | Elasticsearch Guide [8.8] | Elastic

[Elasticsearch:如何基于Script实现按照text属性值的字符串长度排序

https://www.cnblogs.com/mrzihan/p/15729353.html

[Lucene expressions language | Elasticsearch Guide [8.9] | Elastic]

Lucene expressions language | Elasticsearch Guide [8.9] | Elastic

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号