每一个突破下限的 DSL 背后都隐藏着一个“傻X”的客户需求

简介: 每一个突破下限的 DSL 背后都隐藏着一个“傻X”的客户需求

1、事出有因

偶然间在朋友圈看到球友的一次分享,很好奇什么原因导致发了这么大的火!

我们放大看一下,是类似如下的 DSL。

POST my_index_001/_search
{
  "query": {
    "script": {
      "script": {
        "source": """
          def strArrray=doc['name'].value;
          def searchTerm = params.searchTerm;
          def parts=strArrray.splitOnToken(',');
          for (part in parts) {
            if (part.trim().equals(searchTerm)) {
              return true;
            }
          }
          return false;
        """,
        "params": {
          "searchTerm": "一局"
        }
      }
    }
  }
}

而事情的来龙去脉是怎么样的呢?

我们且探个究竟。

2、问题来源

这是一个2024-01-22 21:54 的真实问题。

问题来源:https://t.zsxq.com/16aLaaHrP

问题描述如下:

老师请教一个问题:ES是7.17.7版本。

目前有一个索引,简化之后如下:

PUT my_index
{
  "mappings": {
    "properties": {
      "name":{
        "type": "keyword"
      }
    }
  }
}
 
 
PUT my_index/_doc/1
{
  "name":"一局,二局"
}
 
 
PUT my_index/_doc/2
{
  "name":"三局,十一局"
}

因为历史原因是用逗号隔开存进去的,没存储为数组。

现在想比如搜索“一局”,我是这么写的。

POST my_index/_search
{
  "query": {
    "script": {
      "script": {
        "source": "doc['name'].value.contains('一局')"
      }
    }
  }
}

检索结果如下:

但是有个问题就是,因为十一局也是包含一局的,所以doc2也会被匹配,试了好几种方式都不行,老师能否指点一下。

3、问题解读

实际上问题已经描述得非常清楚了。

数据在存储的时候没有切分,而是以逗号分隔的字符串形式写入的数据。

而现在只想搜索其中的部分数据:“一局”,而如果按照上述的脚本检索方式,“十一局”包含“一局”,会出现文档1、文档2都会被召回的情况。

如果不动索引映射结构,只从检索的角度,只能借助脚本实现。

脚本实现就有了开头的脚本。

其核心部分如下所示:

def strArrray=doc['name'].value;
          def searchTerm = params.searchTerm;
          def parts=strArrray.splitOnToken(',');
          for (part in parts) {
            if (part.trim().equals(searchTerm)) {
              return true;
            }
          }
          return false;

我们通过脚本的方式,拆开字符串,然后进行拆开后的字符串级比较,如果相等,则直接召回数据。

这样就解决了精准匹配的问题。

但,这必然不是最优的方案。

  • 一方面原因:脚本的复杂性,即便再熟悉官方文档,也不能快速写出。这是大家普遍反馈的共识。
  • 另一方面原因:数据量大了,会有性能问题。

有没有其他解决方案?

4、解决方案探讨

4.1 方案一:更新字段,“敌不过来,我就过去”,主动修改字段。

就是新增一个字段,然后通过 update_by_query + pipeline 的方式更新。

PUT _ingest/pipeline/split_pipeline_0126
{
  "processors": [
    {
      "split": {
        "field": "name",
        "separator": ",",
        "target_field": "name_ext"
      }
    }
  ]
}
 
 
 
 
POST my_index/_update_by_query?pipeline=split_pipeline_0126
{
  "query": {
    "match_all": {}
  }
}
 
 
POST my_index/_search

4.2 方案二:重新创建索引,将数据迁移的过程中修改数据。

就是借助:default_pipeline + reindex 方式实现。

PUT my_index_002
{
  "settings": {
    "default_pipeline":"split_pipeline_0126"
  }, 
  "mappings": {
    "properties": {
      "name": {
        "type": "keyword"
      },
      "name_ext": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      }
    }
  }
}
 
 
POST _reindex
{
  "source": {
    "index": "my_index"
  },
  "dest": {
    "index": "my_index_002"
  }
}
  
POST my_index_002/_search

从实现层面和理解层面,如上两种方式的实现都比前文提到的复杂的脚本要复杂一些。

预处理是 Elasticseearch 5.X 就有的功能,在翻看 8.12 新版本官方文档的时候,又有了新的内容。

比如:如下截图,凸显了预处理器 ingest pipeline 在解析日志的强大之处。

这点,基本上和我们上次的发文可以对应上。

5、小结

文章标题来自球友的朋友圈,当然是一时生气的发的个人感慨而已,请大家多关心技术点的实现,不要过度解释。

说一下,DSL 有没有下限呢?取决于我们如何理解业务需求,如何对接业务需求?如何实现业务逻辑?如何技术选型?等.....

如果你也有类似的问题,欢迎抛给我们一起探讨交流。




7 年+积累、 Elastic 创始人Shay Banon 等 15 位专家推荐的 Elasticsearch 8.X新书已上线

《一本书讲透 Elasticsearch》荣登京东编程语言与程序设计榜前5名


相关文章
|
2月前
|
前端开发 JavaScript 开发者
揭秘前端高手的秘密武器:深度解析递归组件与动态组件的奥妙,让你代码效率翻倍!
【10月更文挑战第23天】在Web开发中,组件化已成为主流。本文深入探讨了递归组件与动态组件的概念、应用及实现方式。递归组件通过在组件内部调用自身,适用于处理层级结构数据,如菜单和树形控件。动态组件则根据数据变化动态切换组件显示,适用于不同业务逻辑下的组件展示。通过示例,展示了这两种组件的实现方法及其在实际开发中的应用价值。
52 1
|
6月前
|
Java Spring
通用研发提效问题之配置的若干场景下若干方案的变化该如何解决
通用研发提效问题之配置的若干场景下若干方案的变化该如何解决
|
6月前
|
UED
通用研发提效问题之层级较深表达复杂的问题在配置模型中如何解决
通用研发提效问题之层级较深表达复杂的问题在配置模型中如何解决
|
8月前
|
关系型数据库 Serverless 分布式数据库
国产大模型进入长跑期,从参数至上转向实用优先
近年来,云数据库技术不断发展,为企业提供了更多灵活、高效的数据管理解决方案。在数据库圈中,也有很多好的数据库产品,尤其是国产数据库产品,其中PolarDB作为阿里云的云原生关系型数据库产品,以其强大的Serverless能力备受技术圈的持续关注。很荣幸能够有机会参与体验使用PolarDB的Serverless,由于在日常工作中也会或多或少的用到,正好借此机会体验使用一把。那么本文就来简单的分享一下,从多个维度对PolarDB的Serverless能力进行产品测评,包括资源弹升速度、资源伸缩广度、资源伸缩的稳定性、资源伸缩的颗粒度、可支持自动启停以及全局数据的强一致性,以及与同类型产品进行对比分
108 1
国产大模型进入长跑期,从参数至上转向实用优先
|
数据可视化 测试技术 Python
sum() 函数性能堪忧,列表降维有何良方?
(1)sum() 函数的性能到底差多少,为什么会差?(2)既然 sum() 不是最好的列表降维方法,那是否有什么替代方案呢?
213 0
sum() 函数性能堪忧,列表降维有何良方?
|
小程序 搜索推荐
聚合卡牌盲盒模式系统开发逻辑方案设计程序(成熟代码)
聚合卡牌盲盒模式系统开发逻辑方案设计程序(成熟代码)
327 0
|
SQL 供应链 搜索推荐
案例解析|餐饮行业如何让数字价值收益最大化
020年突如其来的新冠肺炎疫情,对餐饮业的打击首当其冲。据2月12日中国烹饪协会发布的《2020年新冠肺炎疫情对中国餐饮业影响报告》,相比去年春节,疫情期间,78%的餐饮企业营收损失达100%以上;9%的企业营收损失达到九成以上;7%的企业营收损失在七成到九成之间;营收损失在七成以下的仅为5%。这次疫情之变,将会改变很多消费形态,有的其实一直在变化,只是这次之后会加速;有的可能我们还没有想到过,因为疫情,也会带来一些新的变化。本篇文章将以企业A全面上云为案例,详解上云带来的核心价值以及上云方案和步骤,希望能给您的业务带来一定帮助。
346 0
案例解析|餐饮行业如何让数字价值收益最大化
|
SQL 数据库
【自然框架】用CMS的栏目举例,聊一聊从“一层”到“三层”的变化
  做CMS最基本的一个功能就是做一个栏目导航,如果这个导航想做成动态的(即需要从数据库里提取数据)那么要如何实现呢?   简单的方法——DataTable     一个表两个字段,把数据提取出来,放在DataTable里面,然后在页面里做一个循环,OK了。
1176 0