いがにんのぼやき

WEBエンジニアのブログ。IT、WEB、バンド、アニメ。

sqlxでIN句を使う方法

最近Goでsqlxを使っているが、毎回忘れるのでメモ

IN句を用いたクエリ

sqlxでIN句を用いたクエリを使うにはそのままクエリを投げることはできない。
一度 sqlx.In を通してあげる必要がある。

type Hoge struct {
    Id string `db:"id"`
}

db, err := sqlx.Connect("mysql", "接続情報")
if err != nil {
    panic(err)
}

query := `
SELECT id FROM hoge
WHERE id IN (?)
`
idList := []string{"aaa", "bbb", "ccc"}

// 一度sqlx.Inを通してあげる必要がある
query, args, err := sqlx.In(query, idLIst)
if err != nil {
    panic(err)
}
// DBのドライバーに合わせたクエリの変換
query = db.Rebind(query)

var result []*Hoge
err = db.Select(&result, query, args...)
if err != nil {
    panic(err)
}

return result

Selectの結果を別に詰め替えるなら

// 上の結果がresult変数に入っているとして
type Fuga struct {
    Id string
}

// 結果の長さ文の容量を確保したスライスを用意
newResult := make([]*Fuga, 0, len(result))

for _, r := range result {
    newResult = append(newResult, &Fuga{Id: r.Id})
}

return newResult

ここらへんのappendがGo特有というかLLやJavaといった言語ではあまり見ないやり方

IN句に指定する値以外にバインドが必要な場合

SQL:idList のように名前を指定して値をバインドでき、それはもちろんIN句との併用も可能
以下のようにsqlx.Inとsqlx.Namedを組み合わせてクエリを組み立てていく

type Hoge struct {
    Id string `db:"id"`
}

db, err := sqlx.Connect("mysql", "接続情報")
if err != nil {
    panic(err)
}

query := `
SELECT id FROM hoge
WHERE
    id IN (:idList)
    AND data_type = :dataType
`
idList := []string{"aaa", "bbb", "ccc"}
dataType := "xxxType"

input := map[string]interface{}{
    "idList": idList,
    "dataType": dataType,
}

// 最初にsqlx.Named
query, args, err := sqlx.Named(query, input)

// 次にsqlx.In
query, args, err := sqlx.In(query, args...)
if err != nil {
    panic(err)
}
query = db.Rebind(query)

var result []*Hoge
err = db.Select(&result, query, args...)
if err != nil {
    panic(err)
}

return result

決まった手続きなので以下のようなラッパー関数を作ってもいいかもしれない

func NamedInSql(db sqlx.DB, query string, arg interface{}) (string, []interface{}, error) {
    query, args, err := sqlx.Named(query, arg)
    if err != nil {
        return "", nil, err
    }

    query, args, err = sqlx.In(query, args...)
    if err != nil {
        return "", nil, err
    }
    query = db.Rebind(query)
 
    return query, args, err
}

最近ブログ書いてないな

どーも。
お久しぶりです。

何気なくこのブログの最終更新を見たら3月。
ということで9カ月ぶりの更新です。

なんか最近どこかの記事で、ブログとかアウトプットの敷居を下げていこうみたいなのを見て、そうだなと思い筆をとった次第。

もう3月あたりからはずっとコロナでリモートワークで時間の余裕もあるのと(仕事は物凄く忙しいが)、最近はVちゃん https://vtuber-channel.com/ というVTuber情報サイトを開発していたこともあり技術的にちょっとした知見は貯まったので、適度にアウトプットをしていきたい。

今日はその意思表明ってことで。

PS

VTuberに興味がある人Vちゃん使ってくれ

vtuber-channel.com

現在時刻を扱う処理をJavaScriptで書いてPCの時刻を変更して試すとき、ブラウザによって癖がある

現在時刻を扱う処理をJavaScriptで書くことはよくあると思う。ある日時を過ぎていたらリンクを非活性にしたり。
そんなときにブラウザで試そうと思うとPCの時刻を変えるのが手軽なわけだ。
もちろん現在時刻をモックして変えられる仕組みを導入していればいいのだが、WEBフロントエンドではそういう仕組みを導入しているところは少ないんじゃないかと。

じゃあ試してみようと思ってPCの時刻を変えてChromeで試してみると数十秒待たないとその時刻が反映されなかったりする。
Firefoxで試すと即時反映される。ブラウザごとに違うんだなーってことで一旦2ブラウザでどう変わってくるか試してみた。
検証したOSはWindowsMacとかだとまた違うかもしれない。

ブラウザ 現在時刻 タイムゾーン
Chrome タブを新しく開けば更新される、そのまま待っていても数十秒更新されない、ページを更新しても数十秒更新されない 即時反映
Firefox 特に更新もせず即時反映 タブを引き直しても反映されない、Firefox自体を落とさないといけない

Windowsとかだと「日付と時刻」というところから「日付を手動で設定する」のところから日時を変更することが出来る。
んで、ブラウザの開発者ツールからConsoleを開いて new Date と叩けば現在時刻が出てくるのでそれで確認。 f:id:igatea:20200308024107p:plain

現在時刻に加えてタイムゾーンの変更時の挙動も検証してみたらちょっと仕様が違っていて面倒だなと。
SafariやEdgeは検証していないが実際に試してみる場合はこのことを頭に入れておかないとハマりそう。

2019年振り返り

せっかくだし簡単に振り返っていく
総評としてはあまり変化のない1年だったなという感じ
忙しかったんだけど何か新しいこととかはあまりやっていないような

仕事

  • 延々とその会社特有のものを勉強する1年だった
  • 例えばその実装になっている背景や延々とレガシーコードを読むとか
  • 持っているスキルを使って最速でタスクをこなしていく、有識者から仕様を聞き回りレガシーコードを読み業務仕様を追って行った1年
  • 業務知識が増えたことによって視野が広がった
  • チームの人が入れ替わりまくって辛かった、また新しい方が入ってきてチームとして人が増えていろいろやっていけそうで嬉しい
  • 全くのエンジニア実務未経験という方を教えることになったので教える力がついた

プライベート

今年はアウトプットが弱かった年なのでいろいろやっていきたいな、仕事、プライベートどちらも

熱海・伊豆旅行記 2/3 望水編 絶景の海!日の出が見れる旅館!

熱海・伊豆旅行記 2つ目です。

伊豆北川駅

MOA美術館を見た後は熱海駅に戻りそこから伊豆北川駅まで電車移動。
1時間電車に揺られて到着。
そこは無人駅でした。

f:id:igatea:20191124005124j:plain

f:id:igatea:20191124005449j:plain

 駅からの眺め

f:id:igatea:20191124005302j:plain

駅では猫がお出迎え

f:id:igatea:20191124005106j:plain

ただしエサ厳禁

f:id:igatea:20191124005507j:plain

駅から旅館までは10分ほど歩きます。
こんな道を下って、海岸線を歩きます。

f:id:igatea:20191124005605j:plain

弧を描いた海岸線なので端からでも目的地の宿が見えてる

f:id:igatea:20191124005846j:plain

望水到着

やっとこさ到着。
この時点で4時くらいになってたと思う。

宿泊する宿は望水というお宿です。

www.bousui.com

f:id:igatea:20191124010521j:plain

f:id:igatea:20191124010657j:plain

でかい・・・思った以上に。
8階建てなので旅館?にしてはホテルっぽい感じもある。
海岸線の方が入り口かと思ったらこっちは裏口で、正面入り口はどうやら8階らしい。

部屋、ラウンジ

一度8階のラウンジに通された後チェックインを済ませたらお部屋に通されました。
今回は7階のお部屋。
確か一番お安いスタンダードなお部屋だったと思う。

f:id:igatea:20191124022318j:plain

f:id:igatea:20191124021514j:plain

お部屋に通された後はお茶と菓子

f:id:igatea:20191124020642j:plain

温泉

お部屋で少し休んだ後は温泉へ

f:id:igatea:20191124021718j:plain

f:id:igatea:20191124033818j:plain

f:id:igatea:20191124022458j:plain

温泉を上がると湯上りサロンというものがあり、そこでところてんが食べられます

f:id:igatea:20191124014703j:plain

めちゃくちゃ美味しかったところてん
行くことがあれば絶対食べてほしい
わさび味が絶妙にさっぱりしていて最高だった

f:id:igatea:20191124014502j:plain

夕食

温泉で休んだ後はお部屋食

f:id:igatea:20191124020827j:plain

f:id:igatea:20191124015814j:plain

f:id:igatea:20191124020011j:plain

 

f:id:igatea:20191124020030j:plain

f:id:igatea:20191124020942j:plain

f:id:igatea:20191124033645j:plain

f:id:igatea:20191124033704j:plain

f:id:igatea:20191124041521j:plain

どれもこれも美味しかった・・・!

食べた後はプライベートガゼボ

プライベートガゼボ

望水ではプライベートガゼボという特別なお風呂が用意されています。
宿泊者には1回50分が無料でついています。
追加料金払えば回数を増やせるみたいですね。
お部屋に着いた時にいつ入るか聞かれていたので夕食の後の時間でお願いしました。
準備ができたら部屋に電話がかかってくるので向かいます。

そんなお風呂があるんだ〜くらいで向かったら凄かった。

なんだろう・・・完成された空間だった。

f:id:igatea:20191124021256j:plain

f:id:igatea:20191124021337j:plain

f:id:igatea:20191124022018j:plain

f:id:igatea:20191124021402j:plain

f:id:igatea:20191124021323j:plain
この空間で裸になって風呂入ったり、バスローブに包まれてゆったりしたりを繰り返してすごく贅沢で幸せな時間だったw

夜の散策

ガゼボを堪能した後は夜の散策に。

8階の正面入り口の看板

f:id:igatea:20191124015207j:plain

夜の望水

f:id:igatea:20191124022204j:plain

ラウンジでチョコとドリンクが振舞われたり 

f:id:igatea:20191124015306j:plain

f:id:igatea:20191124021432j:plain

1日目満喫できました。
おやすみなさい〜。

f:id:igatea:20191124022108j:plain

2日目は日の出から

望水の大きな特徴として絶対あげたいものが日の出コールというものがあります。
スタッフに伝えておくと日の出が出る時間に部屋に電話して起こしてくれるというもの。
この電話をしてくれることで宿から日の出を眺めることができ最高です。
雲などで隠れて日の出が見れない日はそのままお電話しないとのこと。
今回は運よく日の出が出てお電話が!

日の出が最高に綺麗で良かった!
これが一番いい体験でしたね。

ラウンジからの日の出

f:id:igatea:20191124015033j:plain

部屋から

f:id:igatea:20191124021822j:plain

f:id:igatea:20191124021832j:plain

日の出を浴びる望水

f:id:igatea:20191124040011j:plain

日の出を浴びる伊豆北川温泉

f:id:igatea:20191124040028j:plain

f:id:igatea:20191124040727j:plain

台風の影響で入れなかった黒根岩風呂

f:id:igatea:20191124021047j:plain

朝風呂

朝風呂に入った後はまた湯上りサロンで軽食(温泉は人がいたので写真は撮れなかった)

f:id:igatea:20191124020210j:plain

f:id:igatea:20191124020408j:plain

朝食

朝食ももちろん美味。

海苔が食べ放題でめっちゃ食べてしまった

f:id:igatea:20191124020102j:plain

f:id:igatea:20191124020326j:plain

f:id:igatea:20191124020528j:plain

f:id:igatea:20191124033522j:plain

チェックアウト

日も上がり切ったので部屋からは綺麗な海が見えてまたいい景色

f:id:igatea:20191124041021j:plain

ラウンジからも綺麗

f:id:igatea:20191124040953j:plain

f:id:igatea:20191124021552j:plain

そんなこんなでチェックアウトを済ませて望水、伊豆北川温泉を後に。

f:id:igatea:20191124040905j:plain

f:id:igatea:20191124021119j:plain

 充実しすぎ、写真多すぎでめちゃくちゃ長くなってしまった・・・これは是非足を運んで欲しい、また行きたい宿でした。

次は城ヶ崎海岸へ。

熱海・伊豆旅行記 1/3 熱海探索編 MOA美術館を勧めたい!

つい先週に天皇即位が行われるための祝日とその次の日にお休みをとって熱海と伊豆に旅行に行ってきました。
めちゃくちゃ良かったのでいろんな方にお勧めしたいのと、自分の記録として残しておきます。

1日目

  1. 東京駅から熱海駅
  2. MOA美術館
  3. 伊豆北川温泉の宿、望水に宿泊

2日目

  1. 宿からの日の出
  2. 城ヶ崎海岸
  3. 熱海サンビーチ

ってな感じで行ってきました。
長くなりそうなので記事分けてます。

熱海駅しらす丼

 何はともあれ移動ですね。
新幹線で行ったのですが40〜50分くらいで東京から熱海まで行けてしまうんですよね、新幹線早い。片道も5000円弱。

f:id:igatea:20191104002136j:plain
ささっと駅着いてちょうどお昼くらいの時間だったので商店街に。
結構人もお店もいっぱいで栄えてる感じだった。
新幹線の移動中に何が美味しいかなーと思ってネットで調べていたらこのしらす丼のお店が出てきたのでここに。

tabelog.com

お洒落なカフェ?なんだけどしらす丼がとても美味しかった〜〜〜!

f:id:igatea:20191104001229j:plain

f:id:igatea:20191104001602j:plain

f:id:igatea:20191104001622j:plain

f:id:igatea:20191104001707j:plain

 自分が頼んだのは2食丼で1200円。

MOA美術館へ

熱海にはMOA美術館というものがあり、そこが山の上に建っていることもあり景色が最高らしいと。

www.moaart.or.jp

熱海駅からMOA美術館へはバスで行くことができます。
バスは20分間隔くらいなので乗り遅れないよう気をつけて停留所に。

バスに7分ほど揺られると到着。

f:id:igatea:20191104010729j:plain

チケットはネットで買っておいたのでチケット売り場に並ぶ方々を横目に入場。
入場するとオシャレ空間が始まります。

f:id:igatea:20191104011539j:plain

f:id:igatea:20191104011922j:plain

この階段が数個続いた先の虹色の空間を抜けると一度外に。
そこで初めて美術館の全体を見ることができます。

f:id:igatea:20191104012412j:plain

この景色を振り返ると海!これはたまらない!!

f:id:igatea:20191104012831j:plain

立ち位置によっては熱海城や熱海の海岸を眺めることができます。

展示品は歴史的なもの、美しいものと色々ありこの空間を味わうだけでも大満足。

展示の順路入口

f:id:igatea:20191104013150j:plain

 お洒落オブジェ

f:id:igatea:20191104013026j:plain

f:id:igatea:20191104013103j:plain

平安時代から江戸時代まで幅広い巻物や道具が展示されていたり

f:id:igatea:20191104013344j:plain

f:id:igatea:20191104013430j:plain

f:id:igatea:20191104013450j:plain

f:id:igatea:20191104013617j:plain

 この展示のガラスは映り込みが少ないように工夫されているらしく写真を撮っていても目の前で見ていてもガラスを忘れるようになっています。

展示を一通り見た後は美術資料のある建物の裏にある茶の庭に行ってみました。

f:id:igatea:20191104014430j:plain

綺麗な道を抜けると

f:id:igatea:20191104014511j:plain

お洒落な食事処があったり

f:id:igatea:20191104014549j:plain

f:id:igatea:20191104014600j:plain

当時の暮らしを再現した建物があったり

f:id:igatea:20191104014659j:plain

f:id:igatea:20191104014650j:plain

f:id:igatea:20191104014710j:plain

こんな感じでMOA美術館を満喫してきました。
2時間くらい見ていた気がする。
すっごい楽しかった。

そこからまた熱海駅に戻って旅館に。

次に続きます。

ParcelとFirebase Hostingで簡単サイト公開

ParcelとFirebase Hostingを使ってみて今はこんなに簡単にサイトが作れるんだと感動したので紹介。

先週こんなサイトを公開した。

reiwa-count-up.web.app

ただの悪ふざけで作ったサイト。
平成のカウントアップなのにreiwa-count-upというサブドメインにしたり。
ちょうど令和100日目にこんなツイートをして公開した。

このサイトはParcelとFirebase Hostingを使用して開発している。

parceljs.org

firebase.google.com

Parcelすっごく簡単

Parcelは簡単に言ってしまえばWebpackの簡易版。
指定のHTMLをエンドポイントにHTML、CSS、JSを良しなにまとめてくれる。
例えば以下のHTMLをparcelでビルドするとmain.jsを main.4217b2e0.jsみたいな感じのファイルとして生成してリンクを張り替えてくれる。

<html>
<body>
<script src="main.js"></script>
</body>
</html

JS内での他ファイルのimportももちろん対応している。

import './style.css';
import hoge from './hoge';

hoge();

試していないがDynamic importsなんかも対応しているとのこと。

npm install --save-dev parcel-bundlerでインストールしnpm scriptでparcel index.html で開発用のサーバーが立ち上がる。
標準はdistというディレクトリに出力される。これは-dオプションで出力ディレクトリを変更可能。
開発ではなく本番用のビルドをするにはparcel build index.html

Parcelの気になったところ

Mochaとの組み合わせ。
テストをするときにParcelでビルドされたものをテストする方法が分からなかった。
なのでテストファイルに書いたimportがそのままでは解決できず、Parcelでは必要ない.babelrcを設定する必要が出た。
こんな感じのnpm scriptを用意して、.babelrcを用意してテストを走らせる必要があった。

"test": "cross-env NODE_ENV=test mocha --require babel-register src/js/*.spec.js",

{
  "presets": ["es2015"]
}

あとは特定の画像などをハッシュ付きにしないで出力ディレクトリに出力する方法が分からなかった。
コピープラグインなどあるようだが、Parcelだけだと出来なそう?
SNS用のOGP画像などは https://reiwa-count-up.web.app/hei.png といったメインでの絶対パス指定になるのでhashがついたパスで出力されるとそこがうまく解決できなかった。
なので同じ画像を出力先ディレクトリに保存しておく運用にしている。
buildした後はhei.pnghei.[hash].pngが存在する形になっている。 これはsitemap.xmlなども同じで出力ディレクトリに保存している。

Parcelについてもっと知りたかったらこの記事を見るといいかも。
よくまとまっている。

qiita.com

細かい設定が出来ないが、すごくシンプルなのでプロトタイプや小規模なものをサクッと作るのに良さそう。

Firebase Hosting色々便利

ドメインもらえる!

Firebase自体もちゃんと使うのは初めてで、Hostingを使ってみたがこれがすごい。
まずドメインが貰える。
正確には[プロジェクト名].web.app[プロジェクト名].firebase.comというドメインをもらうことが出来る。
しかもHTTPSにも対応しているのでそのまま使うことが出来る。

f:id:igatea:20190813015853p:plain

凄くいいなと思ったのはxxx.web.appというドメインが設定できること。
なんかアプリ感あるドメインぽくてよくない?
今までHerokuもそうだけどPaaSの製品名がドメインに入っているのが普通だったけど、ちゃんと普通のサイトっぽいドメインをそのまま使えるのはいい。
最初は独自ドメイン当てようかなと思ってたんだけどこんなちょっとしたサイトでドメイン買うのもなーと思っていたら、このドメインだったのでこれはいいと思ってそのまま使った。

CLIでデプロイ簡単、バージョン管理も

プロジェクトディレクトリでfirebase initコマンドを叩くとfirebaseプロジェクトとして設定を行うことができる。
どの機能を使うか(HostingやFirestoreなど)、プロジェクト名などの設定が簡単にできる。
設定後はfirebase deployで即デプロイが可能。
設定ファイルも以下のような数行で終わる程度。

{
  "hosting": {
    "public": "dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}

デプロイするとバージョニングがされ、指定日時にロールバックも可能。 f:id:igatea:20190813020857p:plain

いや~、本当に便利だ。

値段も相当バズったり動画や画像を置きまくらない限り無料プランで完全に賄える。

f:id:igatea:20190813021739p:plain

余談

Google Search Console反映遅すぎ。
3週間くらいかかった。
sitemap.xmlの反映がうまくいってなかったのが原因かもしれないけど。