はじまる

適当な事を適当に書く

Postgres JSON (JSON配列)データの要素にアクセスするための演算子一覧

はじめに

こんなJSONの配列データがあったとします。

[{"a":"foo"},{"b":"bar"},{"c":"baz"}]

PostgreSQL だとこう。

SELECT '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json as example
example
[{"a":"foo"},{"b":"bar"},{"c":"baz"}]

こんなJSONのデータをPostgreSQL で扱う際の演算子と関数一覧です。json型のみでjsonb型は省いています。 元ネタは PostgreSQL 14.0文書です。

演算子

要素にアクセスするための演算子 ->

配列の添字を指定して要素にアクセスする。

SELECT '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json -> 2 as second_element
second_element
{"c":"baz"}

配列の添字(逆順)を指定して配列の要素(オブジェクト)にアクセスする。

SELECT '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json -> -1 as last_element
last_element
{"c":"baz"}

配列の添字(逆順)を指定して配列の要素(オブジェクト)にアクセスし、さらにオブジェクトのキーを指定して値を取得する。 添字の指定にも、オブジェクトのキーの指定にも -> を利用する。

SELECT
    last_element -> 'c' as value -- {"c":"baz"} の key を指定してvalueを得る
FROM
    (
        SELECT
            '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]' :: json -> -1 as last_element
    ) as _
value
"baz"

要素にアクセスしてテキスト型で値を取得するための演算子 ->>

わかりづらいが、ここでの戻り値はテキスト型になっている。

SELECT '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json ->> 0 as str
str
{"a":"foo"}

戻り値はテキスト型のため、JSON型データへの演算子を利用するとエラーになる。

SELECT
    str -> 'a' -- ここで str は '{"a":"foo"}'になっている。
FROM
    (
        SELECT
            '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]' :: json ->> 0 as str
    ) as _
ERROR:  operator does not exist: text -> unknown
LINE 1: SELECT str -> 'a' FROM (
                   ^
HINT:  No operator matches the given name and argument types. You might need to add explicit type casts.

-> と同様にオブジェクトのキーを指定して値にアクセスする場合にも利用できる。

SELECT '{"a":1,"b":2}'::json ->> 'b' as str
str
2

JSONのパスを指定して要素にアクセスするための演算子 #>

{}のなかに、 -> の引数になるような値を書き連ねていくことで、JSON木構造を辿って要素にアクセスできる。

SELECT '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json #> '{0}' as example
example
{"a":"foo"}
SELECT '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json #> '{0,a}' as example
example
"foo"

JSONのパスを指定して要素にアクセスしてテキスト型で値を取得するための演算子 #>>

上記の別バージョンで、戻り値の型がテキスト型になる。

SELECT '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json #>> '{0}' as str
str
{"a":"foo"}
SELECT '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json #>> '{0,a}' as str
str
foo

文字列として保存した PostgreSQL の JSON を Python でも JSON として扱う

はじめに

コーナーケースすぎるけど下記のようなケースです。

  • Python プログラムから直接PostgreSQLに接続するのでなく、Postgres のJSON配列の値を、ほかのデータベースのテキスト型の列か、ファイルなどに、文字列、テキストとして保存する
  • Pythonからはその保存されたデータを読み込んで、PythonJSONとして扱いたい

PostgreSQL

Postgres あるテーブルからデータをJSON 型で抽出するときの小ネタ - はじまる で使った Animals テーブルをまた利用します。

SELECT * FROM Animals;
 id    name   age   kind  
 1    Mickey   5   Mouse
 2    Snoopy   3   Dog
 3    Kitty   3   Cat

これを array_agg などでJSONを格納した配列に変換します。

WITH 
AnimalJSON AS (
    SELECT
        id,
        (
            select
                row_to_json(_)
            from
                (select name, age, kind) as _
        ) as attributes
    FROM
        Animals
)
SELECT
    array_agg(attributes)
FROM
    AnimalJSON
array_agg
{"{\"name\":\"Mickey\",\"age\":5,\"kind\":\"Mouse\"}","{\"name\":\"Snoopy\",\"age\":3,\"kind\":\"Dog\"}","{\"name\":\"Kitty\",\"age\":3,\"kind\":\"Cat\"}"}

この値が適当なデータストアに保存されており、それをPythonで扱いたい時の話です。

Python

上記の array_agg の結果が、文字列として格納されている状態です。Python から読み取り、 str 型の変数 string に入力されているとします。

print(string)
>>>{"{\"name\":\"Mickey\",\"age\":5,\"kind\":\"Mouse\"}","{\"name\":\"Snoopy\",\"age\":3,\"kind\":\"Dog\"}","{\"name\":\"Kitty\",\"age\":3,\"kind\":\"Cat\"}"}

print(repr(string))
>>>'{"{\\"name\\":\\"Mickey\\",\\"age\\":5,\\"kind\\":\\"Mouse\\"}","{\\"name\\":\\"Snoopy\\",\\"age\\":3,\\"kind\\":\\"Dog\\"}","{\\"name\\":\\"Kitty\\",\\"age\\":3,\\"kind\\":\\"Cat\\"}"}'

この string をどうPython での JSONに変えていくかですが、結論としては下記のようなアプローチがいいかと感じました。

  1. str から set に変換する
  2. set から JSON に変換する

まず eval() を使うことで、str から set に型変換します。

>>> string = repr(string)
>>> type(string)
<class 'str'>
>>> eval(string)
{'{"name":"Kitty","age":3,"kind":"Cat"}', '{"name":"Snoopy","age":3,"kind":"Dog"}', '{"name":"Mickey","age":5,"kind":"Mouse"}'}
>>> type(eval(string))
<class 'set'>

ここで、配列の要素はまだ文字列になっています。これらの文字列を json.loads()JSONとしてパースします。

>>> new_list = []
>>> if type(eval(string)) == set:
...   for i in eval(string):
...     item = json.loads(i)
...     new_list.append(item)
... 
>>> new_list
[{'name': 'Kitty', 'age': 3, 'kind': 'Cat'}, {'name': 'Snoopy', 'age': 3, 'kind': 'Dog'}, {'name': 'Mickey', 'age': 5, 'kind': 'Mouse'}]

これでようやくPostgresでの JSONPython でも同様のJSONとして扱えるようになりました。

Python の REPL(対話モード) で for 文などの構文を書く

Mac です。

% uname -a
Darwin hoge 21.3.0 Darwin Kernel Version 21.3.0: Wed Jan  5 21:37:58 PST 2022; root:xnu-8019.80.24~20/RELEASE_ARM64_T6000 arm64

こうなったときどうしたらいいかわからなかった。

% python3
Python 3.8.9 (default, Jul 19 2021, 09:37:30) 
[Clang 13.0.0 (clang-1300.0.27.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = [1,2,3]
>>> for i in a:
...   print(i)
... 

対応は2通り。

  • Shift + Enter を入力する
  • Enter を2回入力する。
% python3
Python 3.8.9 (default, Jul 19 2021, 09:37:30) 
[Clang 13.0.0 (clang-1300.0.27.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = [1,2,3]
>>> for i in a:
...   print(i)
... 
1
2
3

以上。

Postgres あるテーブルからデータをJSON 型で抽出するときの小ネタ

前置き

たまにテーブルのレコードの任意の列をJSONとして抽出したいときがあるので、そのメモ。

前提

こんな 動物 テーブルがあるとします。

SELECT * FROM 動物;
id name age kind
1 Mickey 5 Mouse
2 Snoopy 3 Dog
3 Kitty 3 Cat

テーブルの全ての列をJSONにして抽出する場合

この場合、to_json を利用します。引数はテーブルの名称です。

SELECT to_json(動物) FROM 動物;
to_json
{"id":1,"name":"Mickey","age":5,"kind":"Mouse"}
{"id":2,"name":"Snoopy","age":3,"kind":"Dog"}
{"id":3,"name":"Kitty","age":3,"kind":"Cat"}

抽出する列を絞りたい場合、to_json の引数で列名を指定することはできない為、WITH 句やサブクエリを使いましょう。

WITH 動物2 AS (SELECT id, name FROM 動物)
SELECT to_json(動物2) FROM 動物2;
to_json
{"id":1,"name":"Mickey"}
{"id":2,"name":"Snoopy"}
{"id":3,"name":"Kitty"}

テーブルの一部の列をJSON、一部の列は別の型で同時に抽出する場合

row_to_json を使いましょう。

SELECT
    id,
    (
        select  row_to_json(_)
        from (select name, age, kind) as _
    )
FROM 動物;
id row_to_json
1 {"name":"Mickey","age":5,"kind":"Mouse"}
2 {"name":"Snoopy","age":3,"kind":"Dog"}
3 {"name":"Kitty","age":3,"kind":"Cat"}

参考

Amazon Lightsail と Wordpress を利用したデモ用Webサイト構築

前書き

一般的なWebサーバ/Webアプリケーションのホスティングサービスである、Amazon Lightsail を利用してデモ用Webサイトを構築する手順を紹介します。今回は、Wordpress インスタンス(Bitnami)を利用します。※月間のあいだインスタンスをずっと稼働させているとだいたい月1,000円〜の費用が発生するので、注意してください。

Wordpress インスタンスの構築手順

Lightsail インスタンス

https://lightsail.aws.amazon.com/ls/webapp/home/instances にて、Amazon Lightsail のインスタンスを作成します。「Create Instance」ボタンから、新規インスタンスを作成してください。

Lightsail ダッシュボード
今回は、Platform は Linux/Unix、Select a blueprint では Wordpress を選択します。
Creating a new instance

「Create Instance」ボタンをクリックして、インスタンスが作成されたら、インスタンスの管理画面で、以下を確認してください。

Lightsail Instance

固定IPアドレス

Amazon Lightsail インスタンスは EC2 インスタンス同様、インスタンスを再起動するたびに、公開IPアドレスが変更されます。再起動の都度、公開IPアドレスが変更されてる状態では、公開IPアドレスに安定してドメイン名を設定することができない為、Lightsail インスタンス固定IPアドレスを付与します。LIghtsailインスタンス用の固定IPアドレスは、Lightsailインスタンス管理画面の「Networking」タブから作成できるので、画面操作に従って設定をしてください。

ドメイン

Lightsailインスタンスに固定の公開IPアドレスが付与できたら、そのIPアドレスに紐づける為の任意のドメイン名を取得します。Amazon Route53で購入するとAWSの各種サービスとの連携がやりやすいです。

DNS

ドメイン名が取得できたら、取得したドメイン名とLightsailインスタンスの公開IPアドレスを紐づけられるように、Route53 の設定画面にて、Aレコードを設定します。Route53で購入したドメイン名とLightsailインスタンスの間のAレコード設定は1分程度で伝播されます。

伝播が完了したかの状態はRoute53の画面上に表示されます。完了の表示がでたら、レコードに設定したサブドメインで、Wordpressにアクセスできることを確認してください。

SSL対応

https://aws.amazon.com/jp/premiumsupport/knowledge-center/linux-lightsail-ssl-bitnami/

Lightsail の Bitnami Wordpress インスタンスでは、Bitnami HTTPS Configuration Tool を利用して、Let’s Encryptサーバー証明書を用いたSSL対応が可能です。「Connect using SSH」ボタンからブラウザSSHクライアントを起動、$sudo /opt/bitnami/bncert-tool を実行し、表示される手順にしたがって設定を完了してください。設定が完了したら、HTTPSWordpressにアクセスできることを確認してください。

Wordpress の初期設定

Wordpress 管理画面ログイン

SSL対応が完了したら、Wordpressの管理画面にログインしてみましょう。

https://<ドメイン名>/wp-login.php

デフォルトの管理ユーザーは、ユーザー名 user 、パスワードは、インスタンスのサーバーにSSH接続して、cat bitnami_application_passwordを実行して表示される文字列になります。

ログインに成功すると、Wordpress の管理画面にアクセスできます。ここから、サイトコンテンツの変更やプラグインの追加などをおこなっていきましょう。

カスタムJavaScriptの配置

Wordpress の管理画面では、基本的にWebサイトに JavaScriptCSSを追加することはできません。つまり、下記のようなツールをWebサイトに導入する場合、標準機能以外の手段を利用する必要があります。

プラグインを利用する

Wordpress の各種プラグインで、Webサイトに JavaScriptCSSを追加することが可能です。ここでは「GTM4WPプラグインを追加し、Webサイトの配置するJavaScriptタグの管理をGoogle Tag Manager 経由で行えるようにします。PluginメニューからGTM4WPを検索・インストールし、Settings より下記の手順を実施すれば、以降は Google Tag Manager を通常通り利用できるようになります。

  • Google Tag Manager ID にコンテナIDを入力
  • Container code capability mode を On に設定
  • Save Changes ボタンで保存
直接PHPファイルを編集する

SSHで Lightsails インスタンスのサーバーにログインし、テーマのPHPファイルを編集することでもJavaScriptCSSの更新が可能です。bitnami では /home/bitnami/stack/wordpress/wp-content/themes/<テーマ名>/ にテーマごとのPHPファイルが格納されている為、そのPHPファイルを編集することで、JavaScriptの変更が可能です。

160cm台 男性ファッション セレクトショップスタッフ スタイリングのまとめ

160cm 低身長男性は、なかなか買い物やスタイリングが難しいのですが、最近はセレクトショップのスタッフさんがスタイリング例を公開してくれているので助かります。 わかる範囲でWebで参照可能なスタイリング例をまとめていきたいと思います(随時更新していきます)。

UNITED ARROWS

ユナイテッドアローズさんのオンラインストアでは、ブランド/性別/店舗/身長/カテゴリ("春のコート","ジャケット"など)でスタイリングを検索できます。

Men's|Staff styling|UNITED ARROWS|身長160-164cm

BEAMS

ビームスさんのオンラインストアでは、性別/身長/着用アイテム/着用カラー/レーベル・ショップでスタイリングを検索できます。

www.beams.co.jp

BAYCRUISE

Journal Standard, EDIFICE などを展開するベイクルーズさんでも性別/身長/ブランドでスタイリングを検索できます。 baycrews.jp

FREAK'S STORE

アメカジ中心のセレクトショップFREAK'S STOREさんのオンラインストアではスタッフさんの性別/店舗でスタイリングを検索できます。身長はハッシュタグになっていて、UIでは性別、店舗と身長を掛け合わせた検索はできないんでうが、URLパラメータに &tag=161-165cm を付与することで”161-165cmの男性”を表示することができました。

www.freaksstore.com