体重133キロからのプログラミング

体重はちょっと減って今125キロです。

MySQLで濁音・半濁音がうまく検索できない

対処

  • collationを設定する

経緯

ガンプラ出荷予定を返すアプリを作っていたところ、下記のように濁音・半濁音をうまく検索できていないことを確認。

これに対して、友達がcollationだよと教えてくれた。

f:id:poinorou:20210706000325p:plain

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の管理画面を開き、下記のように設定した。

f:id:poinorou:20210706001852p:plain

初期設定のDBURLに &useUnicode=true&encoding=utf8mb4&collation=utf8mb4_general_ci
を追加しただけである。

これによってcollationとDBの設定が一致するため、想定通りに動作する。

f:id:poinorou:20210706002058p:plain