Elasticsearch实现Mysql的Like效果

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 在Mysql数据库中,模糊搜索通常使用LIKE关键字。然而,随着数据量的不断增加,Mysql在处理模糊搜索时可能面临性能瓶颈。因此,引入Elasticsearch作为搜索引擎,以提高搜索性能和用户体验成为一种合理的选择。

在Mysql数据库中,模糊搜索通常使用LIKE关键字。然而,随着数据量的不断增加,Mysql在处理模糊搜索时可能面临性能瓶颈。因此,引入Elasticsearch作为搜索引擎,以提高搜索性能和用户体验成为一种合理的选择。

1、客户的诉求

在ES中,影响搜索结果的因素多种多样,包括分词器、Match搜索、Term搜索、组合搜索等。有些用户已经养成了在Mysql中使用LIKE进行模糊搜索的习惯。若ES返回的搜索结果不符合用户的预期,可能会引发抱怨,甚至认为系统存在Bug。

谁让客户是上帝,客户是金主爸爸呢,客户有诉求,我们就得安排上。下面我们就聊聊如何用ES实现Mysql的like模糊匹配效果。

如果对Elasticsearch不太熟悉的读者,建议先阅读我之前的文章:

5000字详说Elasticsearch入门

Springboot项目中使用Elasticsearch的RestClient

巧记Elasticsearch常用DSL语法

2、短语匹配match_phrase

2.1、定义

为实现模糊匹配的搜索效果,通常有两种方式,其中之一是match_phrase,先说说match_phrase。

match_phrase短语匹配会对检索内容进行分词,要求这些分词在被检索内容中全部存在,并且顺序必须一致。默认情况下,这些词必须是连续的。

2.2、实验

  • 场景1:创建一个mapping,采用默认分词器(即每个字都当做分词),然后插入两条数据。注意:被搜索的字段先采用text类型。
# 创建mapping,这里的customerName先使用text类型
PUT /search_test
{
  "mappings": {
    "properties": {
      "id": {
        "type": "keyword"
      },
      "customerName": {
        "type": "text"
      }
    }
  },
  "settings": {
    "number_of_shards": 5,
    "number_of_replicas": 1
  }
}

# 插入2条数据
PUT /search_test/_create/1
{
  "id": "111",
  "customerName": "都是生产医院的人"
}

PUT /search_test/_create/2
{
  "id": "222",
  "customerName": "家电清洗"
}

# match_phrase短语匹配查询,可以查出结果
POST search_test/_search
{
  "from": 0,
  "size": 10,
  "query": {
    "bool": {
      "must": [
        {
          "match_phrase": {
            "customerName": "医院的"
          }
        }
      ]
    }
  }
}

以上操作结果显示可以查询到数据。如下图:

  • 场景2:创建一个mapping,采用默认分词器,然后插入两条数据。注意:被搜索的字段先采用keyword类型。
# 创建mapping,这里的customerName先使用text类型
PUT /search_test2
{
  "mappings": {
    "properties": {
      "id": {
        "type": "keyword"
      },
      "customerName": {
        "type": "keyword"
      }
    }
  },
  "settings": {
    "number_of_shards": 5,
    "number_of_replicas": 1
  }
}

# 插入2条数据
PUT /search_test2/_create/1
{
  "id": "111",
  "customerName": "都是生产医院的人"
}

PUT /search_test2/_create/2
{
  "id": "222",
  "customerName": "家电清洗"
}

# match_phrase短语匹配查询,可以查出结果
POST search_test2/_search
{
  "from": 0,
  "size": 10,
  "query": {
    "bool": {
      "must": [
        {
          "match_phrase": {
            "customerName": "医院的"
          }
        }
      ]
    }
  }
}

以上操作结果显示查不到数据。如下图:

2.3、小结

match_phrase短语匹配适用于text类型的字段,实现了类似Mysql的like模糊匹配。然而,它并不适用于keyword类型的字段。

3、通配符匹配Wildcard

为实现模糊匹配的搜索效果,Wildcard通配符匹配是另一种常见的方式。下面我们详细介绍wildcard通配符查询。下面接着说Wildcard通配符查询。

3.1、定义

Wildcard Query 是使用通配符表达式进行查询匹配。Wildcard Query 支持两个通配符:

  • ?,使用 ? 来匹配任意字符。
  • ,使用 来匹配 0 或多个字符。

使用示例:

POST search_test/_search
{
  "query": {
    "wildcard": {
      "customerName": "*测试*"
    }
  }
}

3.2、实验

  • 场景1:创建一个mapping,采用默认分词器,然后插入两条数据。注意:被搜索的字段先采用text类型。使用上文已经创建的索引search_test
# wildcard查询
POST search_test/_search
{
  "from": 0,
  "size": 10,
  "query": {
    "bool": {
      "must": [
        {
          "wildcard": {
            "customerName": {
              "value": "*医院的*"
            }
          }
        }
      ]
    }
  }
}

以上操作结果显示查不到数据,如下图:

注意:如果将DSL查询语句改成只查“医”,就可以查到数据,这与分词器有关。默认分词器将每个字都切成分词。

# Wildcard查询
POST search_test/_search
{
  "from": 0,
  "size": 10,
  "query": {
    "bool": {
      "must": [
        {
          "wildcard": {
            "customerName": {
              "value": "*医*"
            }
          }
        }
      ]
    }
  }
}
  • 场景2:创建一个mapping,采用默认分词器,然后插入两条数据。注意:被搜索的字段先采用keyword类型。使用上文已经创建的索引search_test2
POST search_test2/_search
{
  "from": 0,
  "size": 10,
  "query": {
    "bool": {
      "must": [
        {
          "wildcard": {
            "customerName": {
              "value": "*医院的*"
            }
          }
        }
      ]
    }
  }
}

以上操作结果显示可以查到数据,如下图:

3.3、小结

Wildcard通配符查询适用于keyword类型的字段,实现了类似Mysql的like模糊匹配。然而,它不太适用于text类型的字段。

4、选择分词器

上述实验中均使用了默认分词器的结果。接下来,我们尝试使用IK中文分词器进行实验。

4.1、实验

  • 创建一个名为search_test3的mapping,采用IK中文分词器,然后插入两条数据。注意:被搜索的字段先采用text类型。
PUT /search_test3
{
  "mappings": {
    "properties": {
      "id": {
        "type": "keyword"
      },
      "customerName": {
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart"
      }
    }
  },
  "settings": {
    "number_of_shards": 5,
    "number_of_replicas": 1
  }
}

PUT /search_test3/_create/1
{
  "id": "111",
  "customerName": "都是生产医院的人"
}

PUT /search_test3/_create/2
{
  "id": "222",
  "customerName": "家电清洗"
}
  • 执行搜索,比如搜索“医院的”,无论是match_phrase还是wildcard两种方式都查不到数据。
POST search_test3/_search
{
  "from": 0,
  "size": 10,
  "query": {
    "bool": {
      "must": [
        {
          "match_phrase": {
            "customerName": "医院的"
          }
        }
      ]
    }
  }
}

POST search_test3/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "wildcard": {
            "customerName": {
              "value": "*医院的*"
            }
          }
        }
      ]
    }
  },
  "from": 0,
  "size": 20
}
  • 执行搜索,比如搜索“医院”,match_phrase和wildcard两种方式都可以查到数据。
POST search_test3/_search
{
  "from": 0,
  "size": 10,
  "query": {
    "bool": {
      "must": [
        {
          "match_phrase": {
            "customerName": "医院"
          }
        }
      ]
    }
  }
}

POST search_test3/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "wildcard": {
            "customerName": {
              "value": "*医院*"
            }
          }
        }
      ]
    }
  },
  "from": 0,
  "size": 20
}

4.2、小结

无论是match_phrase还是wildcard两种方式,它们的效果与选择的分词器密切相关。因为两者都是对分词进行匹配,只有匹配到了分词,才能找到对应的文档。

如果搜索内容正好命中了对应的分词,就可以查询到数据。如果没有命中分词,则查不到。在遇到问题时,可以使用DSL查询查看ES的分词情况:

POST _analyze
{  
    "analyzer": "ik_smart",
    "text": "院的人"  
}
POST _analyze
{  
    "analyzer": "ik_smart",
    "text": "医院的"  
}

POST _analyze
{  
    "analyzer": "ik_max_word",
    "text": "都是生产医院的人"  
}

5、总结

match_phrase和wildcard都能实现类似Mysql的like效果。然而,需要注意以下几点:

  • 如果要完全实现Mysql的like效果,最好使用默认分词器,即每个字都切成分词。
  • match_phrase短语匹配,适合于text类型的字段。
  • Wildcard通配符查询,适合于keyword类型的字段。

本篇完结!感谢你的阅读,欢迎点赞 关注 收藏 私信!!!

原文链接:https://mp.weixin.qq.com/s/pXGQsGs1l8msIvP2aJCfWQ

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
4月前
|
关系型数据库 MySQL 数据库
在 MySQL 中使用 LIKE
【8月更文挑战第12天】
309 1
|
24天前
|
搜索推荐 关系型数据库 MySQL
mysql like查询优化
通过合理的索引设计、使用全文索引、优化查询结构以及考虑分片和分区表,可以显著提高MySQL中 `LIKE`查询的性能。针对不同的应用场景选择合适的优化策略,能够有效地提升数据库查询效率,减少查询时间。希望这些方法和技巧能帮助您优化MySQL数据库中的模糊查询。
97 4
|
2月前
|
关系型数据库 MySQL API
MySQL 历史数据迁移到 Elasticsearch
MySQL 历史数据迁移到 Elasticsearch
76 4
|
3月前
|
NoSQL 关系型数据库 Redis
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
mall在linux环境下的部署(基于Docker容器),docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongodb、minio详细教程,拉取镜像、运行容器
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
|
2月前
|
消息中间件 监控 关系型数据库
MySQL数据实时同步到Elasticsearch:技术深度解析与实践分享
在当今的数据驱动时代,实时数据同步成为许多应用系统的核心需求之一。MySQL作为关系型数据库的代表,以其强大的事务处理能力和数据完整性保障,广泛应用于各种业务场景中。然而,随着数据量的增长和查询复杂度的提升,单一依赖MySQL进行高效的数据检索和分析变得日益困难。这时,Elasticsearch(简称ES)以其卓越的搜索性能、灵活的数据模式以及强大的可扩展性,成为处理复杂查询需求的理想选择。本文将深入探讨MySQL数据实时同步到Elasticsearch的技术实现与最佳实践。
113 0
|
3月前
|
搜索推荐 关系型数据库 MySQL
MySQL 模糊查询新纪元:超越 LIKE+% 的高效探索
在数据库的日常操作中,模糊查询是一项不可或缺的功能,它允许我们根据不完全匹配的关键字来检索数据。传统上,MySQL 使用 LIKE 关键字配合 % 通配符来实现这一功能,虽然灵活但性能上往往不尽如人意,尤其是在处理大型数据集时。今天,我们将一起探索几种超越 LIKE+% 的模糊查询技术,以提升查询效率与用户体验。
340 2
|
5月前
|
存储 关系型数据库 MySQL
【Elasticsearch】在es中实现mysql中的FIND_IN_SET查询条件
【Elasticsearch】在es中实现mysql中的FIND_IN_SET查询条件
123 0
|
7月前
|
消息中间件 存储 关系型数据库
【微服务】mysql + elasticsearch数据双写设计与实现
【微服务】mysql + elasticsearch数据双写设计与实现
|
18天前
|
SQL 关系型数据库 MySQL
12 PHP配置数据库MySQL
路老师分享了PHP操作MySQL数据库的方法,包括安装并连接MySQL服务器、选择数据库、执行SQL语句(如插入、更新、删除和查询),以及将结果集返回到数组。通过具体示例代码,详细介绍了每一步的操作流程,帮助读者快速入门PHP与MySQL的交互。
32 1
|
20天前
|
SQL 关系型数据库 MySQL
go语言数据库中mysql驱动安装
【11月更文挑战第2天】
35 4