MySQLで濁音・半濁音がうまく検索できない
対処
- collationを設定する
経緯
ガンプラ出荷予定を返すアプリを作っていたところ、下記のように濁音・半濁音をうまく検索できていないことを確認。
MySQLって濁音・半濁音はうまく検索できないのね… pic.twitter.com/vswIq6opQS
— 片山 (@poihey) 2021年7月4日
これに対して、友達がcollationだよと教えてくれた。
MySQLの検索で濁音・半濁音 | Komekkun.com/blog
ところで、僕はmigrationツールとしてSequelizeライブラリを利用している。 Sequelizeではどう書けばいいだろうかとなったのである。
実装
下記のようにmigrationファイルを作成すればOKだった。
$ sequelize migration:create --name change_collation
これでmigrationファイルが生成される。
'use strict'; module.exports = { up: async (queryInterface, Sequelize) => { await queryInterface.sequelize.query( `ALTER DATABASE ${ queryInterface.sequelize.config.database } CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;` ); /** * Add altering commands here. * * Example: * await queryInterface.createTable('users', { id: Sequelize.INTEGER }); */ }, down: async (queryInterface, Sequelize) => { /** * Add reverting commands here. * * Example: * await queryInterface.dropTable('users'); */ } };
このように、普通にSQL文を実行させるだけ。 これでローカルではOK!ローカルでは・・・
Herokuの本番環境で問題発生
Herokuにデプロイして動かしたところ、以下のようなエラーが出ていた
Error: Illegal mix of collations
HerokuでcleatDBのMySQLを利用すると、初期設定により別の文字コードが指定されているため、書き込みはUTF8で行ってくれない。 そのため、DBに設定されているcollationと初期設定のcollationが異なるため上記のようなエラーを吐く。
これを回避するため、利用している環境変数を変更する必要があるのだが、コンソール上では変更不可だった。(変更した直後に自動的に前の値でheroku config:setされてしまう)
おそらくHerokuの認証が厳しくなったためと思われる。 WebでHerokuの管理画面を開き、下記のように設定した。
初期設定のDBURLに
&useUnicode=true&encoding=utf8mb4&collation=utf8mb4_general_ci
を追加しただけである。
これによってcollationとDBの設定が一致するため、想定通りに動作する。