暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

每一个突破下限的 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名

              文章转载自铭毅天下Elasticsearch,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

              评论