Mysql:Docker的Mysql容器加载Levenshtein 距离算法脚本,实现“相似度匹配”
前言
MySQL自带的Like函数是“包含匹配”,即查询目标需要包含指定条件字符才会匹配到;而“相似度匹配”是匹配目标与条件字符是否相似,例如:“这是北京大学”与 “北大”就会有相似度,这样就会查出这类数据信息,只不过它的相似度分数值比较低而已。
为了实现这个“相似度匹配”需要让Mysql加载一位国外大神编写的函数(UDF)。
下载源码编译
源码地址:https://github.com/juanmirocks/Levenshtein-MySQL-UDF/tree/master

Linux系统可以使用如下命令进行编译。
# 编译文件
gcc -o levenshtein.so -shared levenshtein.c `mysql_config --include`

Mysql容器加载函数
方案一:手动加载
手动加载函数适用已经启动的Mysql容器,容器重启也没问题;但是删除容器重新构建就不可以。
1. 将编译成功的文件“levenshtein.so”放到容器内的Mysql默认工具目录下(/usr/lib/mysql/plugin/)
# 将宿主机的文件 拷贝到 容器内部
docker cp ./levenshtein.so meMysql:/usr/lib/mysql/plugin
2. 注册函数
使用工具软件链接数据库,我这里用的Navicat

执行一下命令
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;


方案二:自动加载
自动加载是在构建Mysql容器时就自己加载好函数,不论如何删除容器都会自动加载函数。
1. 先启动一个mysql容器自身所有工具函数复制到宿主机下
# 先启动一个mysql容器,目的是:将mysql自带的初始化工具函数复制到宿主机
# 复制mysql初始化函数到宿主机
docker cp meMysql:/usr/lib/mysql/plugin /home/mysql/plugin
# 复制完成后,删除这个mysql容器

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

文件内容如下:
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;


卸载函数
如果想卸载函数,使用如下命令:
-- 卸载旧函数(若存在)
DROP FUNCTION IF EXISTS levenshtein;
DROP FUNCTION IF EXISTS levenshtein_k;
DROP FUNCTION IF EXISTS levenshtein_ratio;
DROP FUNCTION IF EXISTS levenshtein_k_ratio;
-----------------------------------
作者:怒吼的萝卜
链接:http://www.cnblogs.com/nhdlb/
-----------------------------------

浙公网安备 33010602011771号