【Go】XormでLIKE演算子を使ってパターンマッチングする(前方一致, 後方一致, 部分一致)
はじめに
Xormの前方一致の書き方で少し迷ったので、忘備録として記事にします。
誰かの役に立てば幸いです。
環境
- go 1.18
- github.com/go-sql-driver/mysql v1.6.0
- xorm.io/xorm v1.2.5
MySQLのLIKE演算子とは
WHERE
句で条件を指定するときに 、LIKE
演算子を使用すると、前方一致や後方一致などパターンマッチングで検索出来ます。
(例1 前方一致)
SELECT * FROM users WHERE name LIKE '田中%';
このように指定すると、usersテーブルのnameカラムの中から、田中〜
というデータを取得します。
(例2 後方一致)
SELECT * FROM users WHERE name LIKE '%太郎';
このように指定すると、usersテーブルのnameカラムの中から、〜太郎
というデータを取得します。
(例3 部分一致)
SELECT * FROM users WHERE name LIKE '%太%';
このように指定すると、usersテーブルのnameカラムの中から、太
が含まれているデータを取得します。
やってみる
それでは、上記をXormで書く方法をやってみます。
DockerでMySQLのDBを作成し、データを挿入し、それをLIKE演算子を使用して検索します。
DB作成
docker-compose.yml
sample_dbという名前のDBを作成します。
docker-compose up -d
でDB作成されます。
version: "3"
services:
db:
image: mysql:5.7
environment:
- MYSQL_DATABASE=sample_db
- MYSQL_ROOT_PASSWORD=root
command: >
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
ports:
- 3306:3306
DBにデータをinsertする
go run main.go
コマンドでDBにデータを追加します。
infra/xorm.go
main.goから呼び出して、DBを初期化します。
func DBInit() *xorm.Engine {
engine, err := xorm.NewEngine("mysql", "root:root@tcp([127.0.0.1]:3306)/sample_db?charset=utf8mb4&parseTime=true")
if err != nil {
log.Fatal(err)
}
// xormで使ったSQLをログに吐きます
engine.ShowSQL(true)
// usersテーブルを初期化します
engine.Sync2(new(model.Users))
return engine
}
model/user.go
下記の構造体を元にDBテーブルが作成されます。
IDはオートインクリメントにしてます。
package model
type Users struct {
ID int `xorm:"id pk autoincr"`
Name string `xorm:"name"`
Address string `xorm:"address"`
}
main.go
func main() {
// engineを作成します。
engine := infra.DBInit()
user1 := model.Users{
Name: "田中太郎",
Address: "大阪府",
}
user2 := model.Users{
Name: "田中隆二",
Address: "京都府",
}
user3 := model.Users{
Name: "佐々木太一",
Address: "東京都",
}
user4 := model.Users{
Name: "佐々木次郎",
Address: "東京都",
}
users := []*model.Users{
&user1,
&user2,
&user3,
&user4,
}
create(*engine, users)
find(*engine)
}
// create ユーザー作成
func create(engine xorm.Engine, users []*model.Users) {
_, err := engine.Table("users").Insert(users)
if err != nil {
log.Fatal(err)
}
fmt.Println("users:", users)
}
// find 複数取得(完全一致)
func find(engine xorm.Engine) {
users := []model.Users{}
// addressが大阪府のuserを全件取得します
err := engine.Where("address = ?", "大阪府").Find(&users)
if err != nil {
log.Fatal(err)
}
fmt.Println("users:", users)
}
上記の内容で
go run main.go
をすると、
下記のようなデータが作成されます。
また、上記のfindの検索結果は完全一致の為、
住所が大阪府である1名だけが取得出来ます。
結果
[xorm] [info] 2022/04/03 15:19:18.242783 [SQL] INSERT INTO `users` (`name`,`address`) VALUES (?, ?),(?, ?),(?, ?) [田中太郎 大阪府 田中隆二 京都府 佐々木太一 東京都 佐々木次郎 東京都] - 15.334537ms
users: [0xc000109e30 0xc000109e60 0xc000109e90]
[xorm] [info] 2022/04/03 15:19:18.251110 [SQL] SELECT `id`, `name`, `address` FROM `users` WHERE (address = ?) [大阪府] - 8.156432ms
users: [{1 田中太郎 大阪府}]
では、次にLIKE検索してみます。
LIKE検索する
Xormでの書き方は以下のようになります。
%
をどのように書くか迷ったけど、+"%"
のように書くらしい。
前方一致
engine.Table("テーブル名")Where("カラム名 LIKE ?", "検索したい文字"+"%")
後方一致
engine.Table("テーブル名")Where("カラム名 LIKE ?", "%"+"検索したい文字")
部分一致
engine.Table("テーブル名")Where("カラム名 LIKE ?", "%"+"検索したい文字"+"%")
main.go
main.goを下記のように変更します。
searchWords
という変数に検索したい文字を入力して使います。
前方一致のメソッドをsearchForwordMatch
後方一致のメソッドをsearchBackwordMatch
部分一致のメソッドをsearchPartialMatch
としました。
使用する時にアンコメントします。
// ここに検索する文字を記載します。
var searchWords string = ""
func main() {
// engineを作成します。
engine := infra.DBInit()
searchForwordMatch(*engine, searchWords)
// searchBackwordMatch(*engine, searchWords)
// searchPartialMatch(*engine, searchWords)
}
// searchForwordMatch 前方一致
func searchForwordMatch(engine xorm.Engine, searchWord string) {
users := []model.Users{}
err := engine.Table("users").Where("name LIKE?", searchWord+"%").Find(&users)
if err != nil {
log.Fatal(err)
}
fmt.Println("users:", users)
}
// searchBackwordMatch 後方一致
func searchBackwordMatch(engine xorm.Engine, searchWord string) {
users := []model.Users{}
err := engine.Table("users").Where("name LIKE?", "%"+searchWord).Find(&users)
if err != nil {
log.Fatal(err)
}
fmt.Println("users:", users)
}
// searchPartialMatch 部分一致
func searchPartialMatch(engine xorm.Engine, searchWord string) {
users := []model.Users{}
err := engine.Table("users").Where("name LIKE?", "%"+searchWord+"%").Find(&users)
if err != nil {
log.Fatal(err)
}
fmt.Println("users:", users)
}
前方一致実行
名前が田中~の人を取得してみます。
-
var searchWords string = "田中"
にします。 - searchForwordMatch(*engine, searchWords)をアンコメントします。
go run main.go
コマンド実行
結果
[xorm] [info] 2022/04/03 15:56:10.500290 [SQL] SELECT `id`, `name`, `address` FROM `users` WHERE (name LIKE?) [田中%] - 12.830607ms
users: [{1 田中太郎 大阪府} {2 田中隆二 京都府}]
田中○○さんを取得出来ました。
後方一致実行
-
var searchWords string = "郎"
にします。 - searchForwordMatch(*engine, searchWords)をコメントアウトします。
- searchForwordMatch(*engine, searchWords)をコメントアウトします。
go run main.go
コマンド実行
結果
[xorm] [info] 2022/04/03 16:22:49.139091 [SQL] SELECT `id`, `name`, `address` FROM `users` WHERE (name LIKE?) [%郎] - 8.410297ms
users: [{1 田中太郎 大阪府} {4 佐々木次郎 東京都}]
○○郎という名前の人を取得出来ました。
部分一致実行
-
var searchWords string = "太"
にします。 - searchBackwordMatch(*engine, searchWords)をコメントアウトします。
- searchPartialMatch(*engine, searchWords)をコメントアウトします。
go run main.go
コマンド実行
結果
[xorm] [info] 2022/04/03 16:26:05.179745 [SQL] SELECT `id`, `name`, `address` FROM `users` WHERE (name LIKE?) [%太%] - 9.484537ms
users: [{1 田中太郎 大阪府} {3 佐々木太一 東京都}]
「太」が入っている人を取得出来ました。
ちなみに、部分一致は、該当の検索ワードは真ん中に無いといけない訳ではなく、文字列のどこかにあれば、ヒットします。
なので、
var searchWords string = "佐"
にすると、
佐々木さんが2人ヒットすることになります。
結果
[xorm] [info] 2022/04/03 16:31:05.152801 [SQL] SELECT `id`, `name`, `address` FROM `users` WHERE (name LIKE?) [%佐%] - 4.939901ms
users: [{3 佐々木太一 東京都} {4 佐々木次郎 東京都}]
さいごに
思ったより簡単に使えました。
部分一致が、中間の文字しか検索出来ないと思ってましたが、中間に限らず、文字列どこかにあればヒットするので、便利に使えそうです。
参考
- https://gobook.io/read/gitea.com/xorm/manual-en-US/
- https://www.dbonline.jp/mysql/select/index7.html
- https://pon3-blog.com/?p=259
Author And Source
この問題について(【Go】XormでLIKE演算子を使ってパターンマッチングする(前方一致, 後方一致, 部分一致)), 我々は、より多くの情報をここで見つけました https://zenn.dev/a_ichi1/articles/95dff34e851b6a著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Collection and Share based on the CC protocol