Gorm で PostgreSQL の JSONB 型の key, value で絞り込む
この記事では、Golang の ORM である Gorm を使って、 PostgreSQL の JSONB 型の中身の key や value による絞り込みをかける方法を紹介しています。
動作環境
- Go 1.10
- PostgreSQL 9.6
Gorm で PostgreSQL の JSONB を絞り込む
モデル
例えば、以下のような、JSON 型の任意のタグを持てるデータ型について考えます。
type TaggedData struct { ID uint32 `gorm:"NOT NULL;primary_key" sql:"TYPE:serial"` Name string `json:"name" gorm:"NOT NULL"` Tags postgres.Jsonb `json:"tags"` }
ここに、3件のデータを登録します。
host := "localhost" user := "postgres" password := "" db := "tagged" client, err := gorm.Open("postgres", fmt.Sprintf( "host=%s user=%s password=%s dbname=%s sslmode=disable", host, user, password, db, )) if err != nil { fmt.Printf("%v\n", err) return } // テーブルを作成 client.AutoMigrate(&TaggedData{}) // データを登録 client.Create(&TaggedData{Name: "data1", Tags: postgres.Jsonb{[]byte(`{"key1": "val1"}`)}}) client.Create(&TaggedData{Name: "data2", Tags: postgres.Jsonb{[]byte(`{"key1": "val1", "key2": "val2"}`)}}) client.Create(&TaggedData{Name: "data3", Tags: postgres.Jsonb{[]byte(`{"key1": "val3", "key2": "val2", "key3": {"key4": "val4"}}`)}})
JSONB の値で検索
例えば Tags
が "key1" == "val1"
のデータを検索してみます。
data := []TaggedData{} // JSONB の値で検索 res := client.Where("tags ->> 'key1' = ?", "val1").Find(&data) if res.Error != nil { fmt.Printf("%v\n", res.Error) return } // 結果を表示 for _, d := range data { fmt.Println(d.Name) }
結果は以下のようになります。
data1 data2
続いて、 "key2" == "val2"
のデータを検索してみます。
res := client.Where("tags ->> 'key2' = ?", "val2").Find(&data)
結果は以下の通りで、data1 の Tags
は "key2"
というフィールドを持っていませんが、エラーにはなりません。
data2 data3
入れ子になっているフィールドを検索することもできます。
// 入れ子のフィールドを検索 res := client.Where("tags #>> '{key3, key4}' = ?", "val4").Find(&data)
こちらも想定通り動きました。結果は以下。
data3
プログラム全体
package main import ( "fmt" "github.com/jinzhu/gorm" "github.com/jinzhu/gorm/dialects/postgres" ) type TaggedData struct { ID uint32 `gorm:"NOT NULL;primary_key" sql:"TYPE:serial"` Name string `json:"name" gorm:"NOT NULL"` Tags postgres.Jsonb `json:"tags"` } func main() { host := "localhost" user := "postgres" password := "" db := "tagged" client, err := gorm.Open("postgres", fmt.Sprintf( "host=%s user=%s password=%s dbname=%s sslmode=disable", host, user, password, db, )) if err != nil { fmt.Printf("%v\n", err) return } client.AutoMigrate(&TaggedData{}) client.Create(&TaggedData{Name: "data1", Tags: postgres.Jsonb{[]byte(`{"key1": "val1"}`)}}) client.Create(&TaggedData{Name: "data2", Tags: postgres.Jsonb{[]byte(`{"key1": "val1", "key2": "val2"}`)}}) client.Create(&TaggedData{Name: "data3", Tags: postgres.Jsonb{[]byte(`{"key1": "val3", "key2": "val2", "key3": {"key4": "val4"}}`)}}) data := []TaggedData{} res := client.Where("tags ->> 'key1' = ?", "val1").Find(&data) if res.Error != nil { fmt.Printf("%v\n", res.Error) return } for _, d := range data { fmt.Println(d.Name) } data = []TaggedData{} res = client.Where("tags ->> 'key2' = ?", "val2").Find(&data) if res.Error != nil { fmt.Printf("%v\n", res.Error) return } for _, d := range data { fmt.Println(d.Name) } res = client.Where("tags #>> '{key3, key4}' = ?", "val4").Find(&data) if res.Error != nil { fmt.Printf("%v\n", res.Error) return } for _, d := range data { fmt.Println(d.Name) } if err := client.DropTable(&TaggedData{}); err != nil { fmt.Printf("%v\n", err) return } }
参考URL
Debian Stretch に protobuf 3.6 をインストール
本記事では Debian 9 Stretch に protobuf 3.6 をインストールする方法を紹介しています。
C++ で gRPC/protobuf を利用するためには、ソースからコンパイルする必要があります。 deb パッケージ提供してほしい。。。
環境
- Debian 9 Stretch
- protobuf v3.6.0
インストール手順
protobuf/README.md at master · google/protobuf · GitHub を参考にインストールします。
依存パッケージのインストール
$ sudo apt-get install autoconf automake libtool curl make g++ unzip
protobuf のリポジトリをクローン
$ git clone https://github.com/google/protobuf.git
$ cd protobuf
$ git checkout v3.6.0
サブモジュールの更新
$ git submodule update --init --recursive $ ./autogen.sh
コンパイル&インストール
$ ./configure $ make # 10分〜20分くらいかかります $ make check # 5分〜10分くらいかかります $ sudo make install $ sudo ldconfig
これで protoc コマンド等が利用できるようになります!
参考URL
Debian Stretch に OpenCV 3.4 をインストール
この記事では Debian Stretch に OpenCV 3系をインストールする手順を紹介しています。
環境
インストール手順
Releases - OpenCV library からインストールしたいバージョンの zip ファイルをダウンロードします。
もしくはコマンドラインからダウンロード。
$ wget https://github.com/opencv/opencv/archive/3.4.0.zip
zip ファイルを展開します。
$ unzip opencv-3.4.0.zip
make && make install します。
$ cd opencv-3.4.0 $ mkdir build && cd build $ cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local .. $ make -j4 # -j4 の部分はCPU数に合わせて変更してください $ sudo make install
これだけ。6コア12スレッドの Core i7 だと make にかかったのは 1〜2分でした、はやい。
参考URL
Debian Stretch で Planex GW-450S を使う
この記事では、Debian Stretch の PC で Planex GW-450S という USB 無線LAN 子機を使えるようにする方法を紹介します。
動作環境
ドライバのインストール手順
以下の手順は対象の PC が有線 LAN 等でインターネットに繋がった状態で作業することを想定しています。
依存パッケージのインストール
$ sudo apt install linux-headers-$(uname -r) # もしくは sudo apt install linux-headers-4.9.0-6-all のように明示的に指定
ドライバーのコンパイルとインストール
$ sudo apt install git
$ git clone https://github.com/abperiasamy/rtl8812AU_8821AU_linux.git
$ cd rtl8812AU_8821AU_linux/
$ make
$ sudo make install
ドライバーの有効化
$ sudo modprobe rtl8812au
上記を実行し、 iwconfig
コマンドやネットワークの設定画面等で無線LANのモジュールが確認できるか、近くのアクセスポイントを検索できるか等を確認します。
上記の設定だけだと、起動時に毎回コマンドを打たないといけないので、/etc/modules
に rtl8812au
を追記することで、起動時にドライバが読み込まれるようにします。
# /etc/modules: kernel modules to load at boot time. # # This file contains the names of kernel modules that should be loaded # at boot time, one per line. Lines beginning with "#" are ignored. rtl8812au
Wi-Fi のインターフェース名の固定
上記を実行して Wi-Fi に接続できた場合は以下の手順は不要です。
SSID のスキャンやパスワード入力は出来るのに、何故か接続できない場合があります。
iwconfig
を実行した際に認識されるインターフェース名が wlan0
ではなく wl.......
のような長い名前になっている場合は、以下の手順を実行します。
/etc/default/grub
の GRUB_CMDLINE_LINUX_DEFAULT
に net.ifnames=0
を追記します。
# If you change this file, run 'update-grub' afterwards to update # /boot/grub/grub.cfg. # For full documentation of the options in this file, see: # info -f grub -n 'Simple configuration' GRUB_DEFAULT=0 GRUB_TIMEOUT=5 GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian` # 以下の行をコメントアウト # GRUB_CMDLINE_LINUX_DEFAULT="quiet" # 以下の行を追加 GRUB_CMDLINE_LINUX_DEFAULT="quiet net.ifnames=0" GRUB_CMDLINE_LINUX=""
そして、以下のコマンドを実行後、PC を再起動します。
$ sudo update-grub
これで問題なく Wi-Fi に繋がるようになりました。
参考サイト
matplotlib でプロット上の点をドラッグする例
Python の matplotlib 上で、マーカーをドラッグ可能にするプログラムの参考例です。
動作環境
- python 2.7
- matplotlib 1.5.3
実装例
使い方
- プロット上で左クリックで点を追加
- プロット上の点をドラッグで移動
- プロット上の点を右クリックで削除
解説
そんなに難しいことはしておらず、matplotlib の canvas に対してマウスイベントを拾って、適切な処理を行うだけです。
- マウスのクリックイベント時のコールバック
_on_click
で新しい点の追加、もしくは既存の点の選択・削除処理 - マウス移動イベント時のコールバック
_on_motion
で選択中の点がある場合は移動処理 - マウスリリースイベント時のコールバック
_on_release
で選択中の点がある場合は確定処理
ちょっとずるいのは、点のX, Y座標を整数に絞ることで、点の管理を簡略化しているところかも。。。
もっと良い実装があれば PR くださーい!