DoctrineのDQLを使ってPostgreSQLの配列型JSONでLIKE検索をする
前回「PostgreSQLの配列型JSONでLIKE検索をする」という記事を書きました。
今回はこれをDoctrineで検索させるかというお話です。
前回調べた内容で発行するクエリ
JSONB型のデータに対してLIKE検索したい場合はサブクエリを使えば解決できました。
|
|
DoctrinenoDQLではどうすればいいのか?
最初はDQL User Defined Functionsを使って jsonb_array_elements_text
を使えるようにすればいいかなと考えました。
自分で作ろうかと思いましたがopsway/doctrine-dbal-postgresql というライブラリが既にあったので使うことにしました。
opsway/doctrine-dbal-postgresqlでjsonb_array_elements_textを使えるようにする
composer requireする以外にも少し作業が必要でした。
composer requireする
まずはcomposer requireします。
|
|
config/doctrine.yamlを変更する
composer requireするだけではだめで、doctrineの設定を変更する必要があります。
|
|
これで jsonb_array_elements_text
がDoctrineで使えるようになりました。
ただし、JSONB_ARRAY_ELEM_TEXT
という名前の関数になっているので間違えないように注意してください。
実際にQueryBuilderで使ってみる
実際にDQLを生成するためのクエリビルダを書いてみましょう。
|
|
これを実行するとエラーが発生します。
|
|
これななぜ起きるのかというとFROM句はクラスを指定する想定になっているからエラーが発生します。
つまり、FROM句はEntityしか指定できないということですね。
ChatGPTに聞くと以下のように言ってました。
DQLの主な目的は、エンティティとその関連をクエリすることです。そのため、FROM句では、通常エンティティ(つまり、データベースのテーブルにマップされたクラス)の名前が必要です。そして、SELECT句では、エンティティのプロパティ(つまり、テーブルの列にマップされたクラスのフィールド)を指定します。 したがって、DQLでFROM句に関数を使用することはできません。
つまりDQLだとサブクエリを使ったLIKE検索は無理だということになります。
CASTを使う
PostgreSQLにはCASTをする機能があります。
JSON型からTEXT型に変換することも可能になります。つまりこういうSQLでも同じ結果が得られることです。
|
|
CAST関数を作る
もちろんDQLの場合はCAST関数を作ることはできません。
ということで関数を作ります。
|
|
さらにconfig/doctrine.yamlにも追記が必要です。
|
|
QueryBuilderを修正する
クエリビルダを修正します。
|
|
これで無事検索できるようになりました。
まとめ
- DQLではFROM句はEntityのみ指定できる
- サブクエリを使った検索方法はDQLでは無理
- CASTを使ってLIKE検索をする
参考
Symfony find user by role (JSON array Doctrine property)
https://t.co/oXQ1Qs5OYl
— たつきち🍤PHPカンファレンス名古屋実行委員長 (@ttskch) May 10, 2023
これでできますよ