Mysql:Docker的Mysql容器加载Levenshtein 距离算法脚本,实现“相似度匹配”

 前言

  MySQL自带的Like函数是“包含匹配”,即查询目标需要包含指定条件字符才会匹配到;而“相似度匹配”是匹配目标与条件字符是否相似,例如:“这是北京大学”与  “北大”就会有相似度,这样就会查出这类数据信息,只不过它的相似度分数值比较低而已。

  为了实现这个“相似度匹配”需要让Mysql加载一位国外大神编写的函数(UDF)。

下载源码编译

源码地址:https://github.com/juanmirocks/Levenshtein-MySQL-UDF/tree/master

image

Linux系统可以使用如下命令进行编译。

# 编译文件
gcc -o levenshtein.so -shared levenshtein.c `mysql_config --include`

image

Mysql容器加载函数

方案一:手动加载

手动加载函数适用已经启动的Mysql容器,容器重启也没问题;但是删除容器重新构建就不可以。

1. 将编译成功的文件“levenshtein.so”放到容器内的Mysql默认工具目录下(/usr/lib/mysql/plugin/)

# 将宿主机的文件 拷贝到 容器内部
docker cp ./levenshtein.so meMysql:/usr/lib/mysql/plugin

2. 注册函数

使用工具软件链接数据库,我这里用的Navicat

image

执行一下命令

CREATE FUNCTION levenshtein         RETURNS INT  SONAME 'levenshtein.so';
CREATE FUNCTION levenshtein_k       RETURNS INT  SONAME 'levenshtein.so';
CREATE FUNCTION levenshtein_ratio   RETURNS REAL SONAME 'levenshtein.so';
CREATE FUNCTION levenshtein_k_ratio RETURNS REAL SONAME 'levenshtein.so';

测试以下命令

select levenshtein_ratio('这是北京大学', '北大') as ratio;

select levenshtein_ratio('这是北京大学', '北京大学') as ratio;

image

image

方案二:自动加载

自动加载是在构建Mysql容器时就自己加载好函数,不论如何删除容器都会自动加载函数。

1. 先启动一个mysql容器自身所有工具函数复制到宿主机下

# 先启动一个mysql容器,目的是:将mysql自带的初始化工具函数复制到宿主机
# 复制mysql初始化函数到宿主机
docker cp meMysql:/usr/lib/mysql/plugin /home/mysql/plugin

# 复制完成后,删除这个mysql容器

image

2. 编写容器启动后运行的sql命令文件

 这里我创建了一个目录,用于存放启动后运行的sql命令文件。

image

文件内容如下:

udf-levenshtein.sql
CREATE FUNCTION levenshtein         RETURNS INT  SONAME 'levenshtein.so';
CREATE FUNCTION levenshtein_k       RETURNS INT  SONAME 'levenshtein.so';
CREATE FUNCTION levenshtein_ratio   RETURNS REAL SONAME 'levenshtein.so';
CREATE FUNCTION levenshtein_k_ratio RETURNS REAL SONAME 'levenshtein.so';

3. 配置docker-compose.yml文件

我一般使用docker compose构建容器,所以这里是我的docker-compose.yml文件配置

#version: "3.8"
networks:
  temp_net:
    name: temp_net
    ipam:
      config:
        - subnet: 172.19.8.0/24
services:
  # Mysql数据库
  mysql:
    container_name: meMysql
    image: mysql:8.0.39-debian
    restart: always
    environment:
      TZ: Asia/Shanghaidoc        # 配置时间为上海时间
      MYSQL_ROOT_PASSWORD: 123456        # 配置mysql密码
      MYSQL_ROOT_HOST: '%'        # 设置用户开启远程连接
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
        max-file: "10"            # 设置日志文件个数
    ports:
      - 3306:3306
    networks:
      temp_net:
        ipv4_address: 172.19.8.100
    command: [
      "--character-set-server=utf8mb4",    # 设置库的字符集
      "--collation-server=utf8mb4_general_ci",    # 默认排序方式
      "--default-authentication-plugin=mysql_native_password",    # 远程登录密码与用户设置的密码一致
      "--sql-mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
    ]
    volumes:
      - /home/mysql/data:/var/lib/mysql    # 挂载mysql数据目录
      - /home/mysql/conf/my.cnf:/etc/mysql/conf.d/my.cnf    # 挂载mysql配置文件
      - /home/mysql/plugin:/usr/lib/mysql/plugin    # 挂载mysql工具目录
      - /home/mysql/init:/docker-entrypoint-initdb.d  # 容器启动后,会自动运行这个目录下的 *.sql 文件

 

启动后,就可以测试以下命令

select levenshtein_ratio('这是北京大学', '北大') as ratio;

select levenshtein_ratio('这是北京大学', '北京大学') as ratio;

image

image

卸载函数

如果想卸载函数,使用如下命令:

-- 卸载旧函数(若存在)
DROP FUNCTION IF EXISTS levenshtein;
DROP FUNCTION IF EXISTS levenshtein_k;
DROP FUNCTION IF EXISTS levenshtein_ratio;
DROP FUNCTION IF EXISTS levenshtein_k_ratio;

 

posted @ 2025-09-18 10:19  怒吼的萝卜  阅读(32)  评论(0)    收藏  举报