Help us understand the problem. What is going on with this article?

MySQL8.0で全文検索(mecab)を試してみる。

この記事はディップ Advent Calendar 2019の19日目の記事です。

まえがき

DockerでMySQL8.0の全文検索機能をお試しする環境をつくってみます。
そもそも全文検索って何なのさ、というのは以下の記事がとても参考になります。
検索エンジンはいかにして動くのか?

なお、コンテナ作成後のSQLは、ホストからMySQL Workbenchで接続・実行しています。
※dockerコンテナの中からmysql clientで接続して、最後の全文検索用SQLを投げようとしたところ、日本語を入力した途端に文字が消えるという事象に遭遇し、断念。。

構築手順

フォルダ構成
.
├── docker   
│   └── mysql8.0-mecab
│       ├── Dockerfile
│       ├── conf.d
│       │   └── my.cnf
│       └── initdb.d
│           └── init.sql
├── docker-compose.yml

上のようなフォルダ構成で、下記のファイルを用意していきます。

docker-compose.yml

my.cnfはローカルからコンテナの/etc/mysql/conf.dにマウントさせてます。
また、/docker-entrypoint-initdb.dにマウントされたシェルスクリプトやSQLが初回起動時に実行されます。
今回はmecabプラグインのインストールや検証用テーブル作成用のSQLを配置しました(後述)。

docker-compose.yml
version: '3.3'
services:
  mysql80-mecab:
    build: ./docker/mysql8.0-mecab
    container_name: mysql8.0-mecab
    environment:
      MYSQL_DATABASE: sample_db
      MYSQL_USER: jabe
      MYSQL_PASSWORD: jabe123
      MYSQL_ROOT_PASSWORD: jabe123
      TZ: 'Asia/Tokyo'
    ports:
      - "3306:3306"
    volumes:
      - ./docker/mysql8.0-mecab/conf.d:/etc/mysql/conf.d
      - ./docker/mysql8.0-mecab/initdb.d:/docker-entrypoint-initdb.d

Dockerfile

mecabのインストールをします。また、echo "dicdir=/var/lib/mecab/dic/ipadic-utf8" > /etc/mecabrc の部分でmecabの単語辞書をIPA辞書に切り替えています。

Dockerfile
FROM mysql:8.0
RUN apt-get update && apt-get install -y        \
    mecab                                       \
    libmecab-dev                                \
    mecab-ipadic-utf8                           \
    locales                                     \
&&  locale-gen ja_JP.UTF-8                      \
&&  echo "dicdir=/var/lib/mecab/dic/ipadic-utf8" > /etc/mecabrc
ENV LANG        ja_JP.UTF-8
ENV LC_CTYPE    ja_JP.UTF-8

my.cnf

MySQLにmecabrc(mecabの設定ファイル。前述のDockerfileで単語辞書のパスを記載しました。)のパスを通します。
また、mecabがトークン解析をする際のトークンの分割単位を決めます。

my.cnf
[mysql]
default-character-set=utf8mb4
[client]
default-character-set=utf8mb4
[mysqld]
# mecabrcファイルの格納先
loose-mecab-rc-file=/etc/mecabrc
# mecabが解析時にトークン分割する際のトークンサイズを指定
innodb_ft_min_token_size=1
# デフォルト認証プラグインの設定
default-authentication-plugin = mysql_native_password

collation-server=utf8mb4_unicode_ci
character-set-server=utf8mb4
skip-character-set-client-handshake

初期化用SQL

前述のコンテナ初回起動時に実行させるSQLです。ここでは以下をやっています。

  1. mecabプラグインのインストール
  2. テーブル作成&初期データ投入

特に、fulltext (street_address) with parser mecab で全文検索用のindexを作成します。

init.sql
use sample_db;
/*** 1. mecabプラグインのインストール ***/
install plugin mecab soname 'libpluginmecab.so';

/*** 2. テーブル初期化 ***/
drop table if exists employee;
create table employee
(
        id                          int unsigned auto_increment not null primary key
    ,   name                        varchar(40)
    ,   street_address              varchar(90)
    ,   fulltext (street_address)   with parser mecab
) engine=innodb character set utf8mb4;

insert into employee (id, name, street_address) values (1, "太郎","東京都新宿区");
insert into employee (id, name, street_address) values (2, "次郎","京都府京都市北区");
insert into employee (id, name, street_address) values (3, "三郎","愛媛県松山市");
insert into employee (id, name, street_address) values (4, "四郎","香川県高松市");
insert into employee (id, name, street_address) values (5, "五郎","徳島県徳島市");
insert into employee (id, name, street_address) values (6, "花子","高知県高知市");

コンテナ起動&確認

docker-composeコマンドでコンテナの起動、確認します。

# 起動
$ docker-compose up -d
# 起動確認
$ docker-compose ps 
# ログチェック
$ docker-compose logs

DB確認

コンテナ起動後、MySQLにログインし、以下が確認できればOKです!

  1. mecabプラグインがあること。
  2. テーブル作成&初期データ登録ができてること。
MySQLの状態確認。
Execute:
> show create table employee

+ ---------- + ----------------- +
| Table      | Create Table      |
+ ---------- + ----------------- +
| employee   | CREATE TABLE `employee` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(40) DEFAULT NULL,
  `street_address` varchar(90) DEFAULT NULL,
  PRIMARY KEY (`id`),
  FULLTEXT KEY `street_address` (`street_address`) /*!50100 WITH PARSER `mecab` */ 
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+ ---------- + ----------------- +
1 rows

Execute:
> select * from employee

+ ------- + --------- + ------------------- +
| id      | name      | street_address      |
+ ------- + --------- + ------------------- +
| 1       | 太郎    | 東京都新宿区            |
| 2       | 次郎    | 京都府京都市北区         |
| 3       | 三郎    | 愛媛県松山市            |
| 4       | 四郎    | 香川県高松市            |
| 5       | 五郎    | 徳島県徳島市            |
| 6       | 花子    | 高知県高知市            |
+ ------- + --------- + ------------------- +
7 rows

いざ、全文検索。

「京都」を検索して「東京都」がでなければ、できあがり。

Execute:
> select * from employee
where match (street_address)
against ('京都' in natural language mode)

+ ------- + --------- + ------------------- +
| id      | name      | street_address      |
+ ------- + --------- + ------------------- +
| 2       | 次郎    | 京都府京都市北区        |
+ ------- + --------- + ------------------- +
2 rows

あとがき

最後までお付き合い頂きありがとうございました。
不備、おかしなところあれば、ご指摘頂けますと幸いです。
また、まえがきで遭遇した事象について有力情報お待ちしておりますm(_ _)m

参考記事

以下を参考にさせていただきました。感謝です。
https://dev.mysql.com/doc/refman/8.0/en/fulltext-search-mecab.html
https://qiita.com/clustfe/items/3f5160ce77c5db9c7b30
https://qiita.com/ucan-lab/items/b094dbfc12ac1cbee8cb
https://qiita.com/motoki_giants/items/0c3b9d174edef9410310
https://qiita.com/furu8ma/items/75e5b1df29fef04ec7f1

jabe
dip-net
ディップ株式会社は「バイトル」「はたらこねっと」などの求人情報サービスをはじめ、人工知能専門メディア「AINOW」、スタートアップ専門メディア「スタートアップタイムズ」、アニメなどの舞台を紹介するサイト「聖地巡礼マップ」といった新しい分野のサービスを自社で開発・運営しています。
https://www.dip-net.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした