dak ブログ

python、rubyなどのプログラミング、MySQL、サーバーの設定などの備忘録。レゴの写真も。

BigQuery で array<struct<...>> にデータを登録する方法

2022-06-28 23:50:53 | GCP
BigQuery で array<struct<...>> のフィールドにデータを登録する方法のメモ。
■テーブル定義
create table `items` (
  item_id      string,
  store_id     string,
  stock        integer
);

create table `item_store_infos` (
  item_id          string,
  store_infos      array<
    struct<
      store_id     string,
      stock        integer
    >
  >
);

■登録
items テーブルから items_store_info テーブルにデータを登録。
insert into
  `item_store_infos`
(item_id, store_infos)
select
  item_id
  , store_infos
from (
  select
    item_id
    , array_agg(store_info) as store_infos
  from (
      select item_id, struct(store_id, stock) as store_info from `itmes`
  ) s
  group by
    item_id
);



MySQL の datetime でミリ秒、マイクロ秒の日時を登録

2022-06-22 23:49:51 | MySQL
MySQL の datetime でミリ秒、マイクロ秒の日時を登録する方法のメモ。
datetime のカラムは秒まで、datetime(3) でミリ秒まで、datetime(6) でマイクロ秒までの精度となります。

■テーブル定義
create table dt1 (
  dt0       datetime,
  dt3       datetime(3),
  dt6       datetime(6),
  auto_dt0  datetime default current_timestamp,
  auto_dt3  datetime(3) default current_timestamp(3),
  auto_dt6  datetime(6) default current_timestamp(6)
);


■データ登録
insert into
  dt1
set
  dt0 = current_timestamp()
  , dt3 = current_timestamp(3)
  , dt6 = current_timestamp(6);


■検索
mysql> select * from dt1\G
*************************** 1. row ***************************
     dt0: 2022-06-22 07:45:42
     dt3: 2022-06-22 07:45:42.383
     dt6: 2022-06-22 07:45:42.383531
auto_dt0: 2022-06-22 07:45:42
auto_dt3: 2022-06-22 07:45:42.383
auto_dt6: 2022-06-22 07:45:42.383531


MySQL で json オブジェクトを登録

2022-06-20 23:44:47 | MySQL
MySQL で json オブジェクトを登録する方法のメモ。

■テーブル定義
create table json1 (
  id   varchar(16) not null,
  obj  json
);


■データ登録
insert into json1 set id = '01', obj = json_array(1, 2, 3);
insert into json1 set id = '02', obj = json_object("key1", 1, "key2", 2, "key3", 3);


■検索
mysql> select * from json1;
+----+-----------------------------------+
| id | obj                               |
+----+-----------------------------------+
| 01 | [1, 2, 3]                         |
| 02 | {"key1": 1, "key2": 2, "key3": 3} |
+----+-----------------------------------+


MySQL で検索結果を csv ファイルに出力

2022-06-20 23:02:06 | MySQL
MySQL で検索結果を csv ファイルに出力する方法のメモ。

MySQL で secure_file_priv が有効な場合は、出力ファイルは
secure_file_priv のディレクトリを指定する必要があります。
mysql> show variables like 'secure_file_priv';
+------------------+-----------------------+
| Variable_name    | Value                 |
+------------------+-----------------------+
| secure_file_priv | /var/lib/mysql-files/ |
+------------------+-----------------------+


select 文は以下のようになります。
・fields terminaterd by で ',' を指定
・enclosed by で '"' を指定
・escaped by で '\\' を指定
select
  *
into outfile
  '/var/lib/mysql-files/export.csv'
fields terminated by
  ','
enclosed by
  '"'
esaped by
  '\\'
from
  tbl
;


Cloud SQL で Cloud Storage 上の tsv ファイルをインポート

2022-06-20 22:42:18 | GCP
Cloud SQL で Cloud Storage 上の tsv ファイルをインポートする方法のメモ。

以下のオプションで csv として読み込む。
・--fields-terminated-by で区切り文字にタブ(0x09)を指定
・-llines-terminated-by で改行(0x0A)を指定
・--quote でので囲み文字を指定しない
gcloud sql import csv \
       {cloud_sql_instance_id} \
       gs://{bucket}/{file.tsv} \
       --database={database_name} \
       --table={table_name} \
       --fields-terminated-by="09" \
       --lines-terminated-by="0A"


<img src="data:..."> での画像指定

2022-06-18 23:35:37 | python
<img src="data:..."> で画像を指定する方法のメモ。
python で <img src="data:..."> で画像を指定するプログラムを作成してみました。

■サーバ
import sys
import requests
import io
import base64
from PIL import Image
from flask import Flask, jsonify

app = Flask(__name__)

def image_base64(bytes):
    inst = io.BytesIO(bytes)
    img = Image.open(inst).convert('RGB')
    inst.close()

    outst = io.BytesIO()
    img.save(outst, format='PNG')
    img_data = outst.getvalue()
    outst.close()

    img_base64 = base64.b64encode(img_data).decode('utf-8')

    return img_base64

@app.route('/')
def view_html():
    img_url = 'https://www.xgoo.jp/top2018/public/img/img_socialmark.png'
    res = requests.get(img_url)

    img_base64 = image_base64(res.content)

    html = f'''
<html>
<head>
<meta http-equv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<img src="data:image/png;base64,{img_base64}">
</body>
</html>
'''
    return html


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000)


■html
上記のサーバに "http://localhost:8000/" でアクセスした際のレスポンスは以下のようになります。
<html>
<head>
<meta http-equv=&quote;Content-Type&quote; content=&quote;text/html; charset=utf-8&quote;>
</head>
<body>
<img src="data:image/png;base64,...">
</body>
</html>


mecab-python3 のインストール

2022-06-14 22:08:50 | python
CentOS8 で mecab-python3 をインストールする方法のメモ

■mecab のインストール
sudo yum install mecab mecab-ipadic


■mecab-python3 のインストール
現時点で最新の 1.0.5 だとインストールに失敗するため、1.0.4 をインストールします。
pip install mecab-python3==1.0.4


■mecabrc
sudo ln -s /etc/mecabrc /usr/local/etc/mecabrc


gunicorn + flask でマルチプロセス

2022-06-10 21:51:17 | python
gunicorn + flask でマルチプロセスのウェブアプリケーションを作成する方法のメモ。

■インストール
pip install gunicorn
pip install flask


■プログラム構成
test.py: ウェブアプリケーション本体
settings.py: gunicorn の設定

■test.py
3秒スリープして、サーバのプロセスIDを含む文字列を返却します。
import os
import time
from flask import Flask

app = Flask(__name__)

@app.route('/test')
def view_test():
    time.sleep(3)
    pid = os.getpid()
    msg = f'''hello world ({pid})\n'''
    return msg


■settings.py
以下は 4 ワーカー(プロセス)でアプリケーションを実行する例です。
bind = '127.0.0.1:8000'
proc_name = 'test'
workers = 4


■ウェブアプリケーション実行
gunicorn test:app -c settings.py

実行すると、以下のように複数のプロセスIDで worker が
[4942] [INFO] Booting worker with pid: 4942
[4943] [INFO] Booting worker with pid: 4943
[4944] [INFO] Booting worker with pid: 4944
[4945] [INFO] Booting worker with pid: 4945


■サーバにアクセス
curl コマンドを & をつけて4回実行してみます。
curl 'http://localhost:8000/test'&
curl 'http://localhost:8000/test'&
curl 'http://localhost:8000/test'&
curl 'http://localhost:8000/test'&

以下のように複数のプロセスからレスポンスがあったことが確認できます。
hello world (4944)
hello world (4943)
hello world (4942)
hello world (4945)


BigQuery で文字列から数値の配列を生成

2022-06-08 22:44:39 | GCP
BigQuery で文字列から数値の配列を生成する方法のメモ。
select
  array(select cast(e as float64) from unnest(split("1, 2, 3", ",")) e) as vector
;


Elasticsearch 8.X を http で起動

2022-06-05 22:29:38 | elasticsearch
Elasticsearch 8.X で security 設定を外して起動する方法のメモ。

config/elasticsearch.yml に以下を記述して elasticsearch を起動します。
discovery.type: single-node
xpack.security.enabled: false
xpack.security.audit.enabled: false
xpack.security.transport.ssl.enabled: false


flask でのパラメータ取得

2022-06-03 23:41:00 | python
flask でのパラメータ取得方法のメモ。

GET、POST でのパラメータの取得と、ファイルの受信方法をまとめてみました。

■GET
プログラム
import sys
from flask import Flask, request

app = Flask(__name__)

@app.route('/', methods=["GET"])
def view_get():
    var1 = request.args.get('var1', '')
    return f'''var1={var1}\n'''

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)


リクエスト
curl -X GET 'http://localhost:8080/?var1=foo'


レスポンス
var1=foo


■POST
プログラム
import sys
from flask import Flask, request

app = Flask(__name__)

@app.route('/', methods=["GET", "POST"])
def view_get():
    if request.method == "GET":
        val1 = request.args.get('var1', '')
        val2 = request.args.get('var2', '')
    elif request.method == "POST":
        val1 = request.form.get('var1', '')
        val2 = request.form.get('var2', '')

    return f'''var1={val1}\nvar2={val2}\n'''

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)


リクエスト
curl 'http://localhost:8080/' \
     -X POST \
     -F 'var1=foo' \
     -F 'var2=bar'


レスポンス
var1=foo
var2=bar


■ファイルの受信
プログラム
import sys
from flask import Flask, request

app = Flask(__name__)

@app.route('/', methods=["POST"])
def view_get():
    val1 = request.form.get('var1', '')
    val2 = request.form.get('var2', '')
    file1 = request.files.get('file1')

    bytes = file1.stream.read()
    str = bytes.decode('utf-8')

    return f'''var1={val1}\nvar2={val2}\nfile1={str}\n'''

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)


リクエスト
curl 'http://localhost:8080/' \
     -X POST \
     -F 'var1=foo' \
     -F 'var2=bar' \
     -F 'file1=@file.txt'


レスポンス
var1=foo
var2=bar
file1=abc