😽

StreamlitのアプリからSnowflakeのデータを更新する

に公開

はじめに

Snowflake UniversityのHands OnシリーズのBadge 3でStreamlitのアプリを作成したので、
StreamlitのアプリからSnowflakeのデータを更新する実装方法をまとめてみました。
https://learn.snowflake.com/en/courses/OD-ESS-DABW/

説明すること

  • 実装したPythonコード
  • アプリを使用したデータの更新方法

説明しないこと

  • 環境構築の手順
  • Snowflakeへの接続方法の詳細

前提条件

Pythonのバージョンは3.11を使用しました。
アプリでは、以下のテーブルのORDER_FILLEDのデータ(BOOLEAN型)を更新します。

create or replace TABLE SMOOTHIES.PUBLIC.ORDERS (
	ORDER_UID NUMBER(38,0),
	ORDER_FILLED BOOLEAN DEFAULT FALSE,
	NAME_ON_ORDER VARCHAR(100),
	INGREDIENTS VARCHAR(200),
	ORDER_TS TIMESTAMP_LTZ(9) DEFAULT CURRENT_TIMESTAMP(),
	constraint ORDER_UID unique (ORDER_UID)
);

アプリの実装

まずは、今回実装したPythonコードとアプリからのデータの更新方法を紹介します。

実装したコード

# 必要なパッケージをインポート
import streamlit as st
from snowflake.snowpark.functions import col, when_matched

# タイトル・テキストの表示
st.title(f":cup_with_straw: 保留中のスムージー注文:cup_with_straw:")
st.write(
  """
  処理が必要な注文
  """
)

# セッションの取得
cnx = st.connection("snowflake")
session = cnx.session()

my_dataframe = session.table("smoothies.public.orders").filter(col("ORDER_FILLED")==0).collect()

if my_dataframe:
    editable_df = st.data_editor(my_dataframe,disabled=["ORDER_UID","NAME_ON_ORDER","INGREDIENTS","ORDER_TS"])
    submitted = st.button('送信')

    if submitted:
        
        og_dataset = session.table("smoothies.public.orders")
        edited_dataset = session.create_dataframe(editable_df)

        try:
            og_dataset.merge(edited_dataset
                     , (og_dataset['ORDER_UID'] == edited_dataset['ORDER_UID'])
                     , [when_matched().update({'ORDER_FILLED': edited_dataset['ORDER_FILLED']})]
                    )

            st.success("注文が更新されました!", icon="👍")
        except:
            st.write('問題が発生しました')

else:
    st.success('現在、保留中の注文はありません', icon="👍")

アプリでのデータ更新

  1. アプリ起動時の画面
    起動時画面

  2. 更新するORDER_FILLEDのカラムにチェックを入れる
    チェック画面

  3. 送信ボタンをクリックしデータを更新する
    更新画面

実装コードの説明

ここからは実装したコードについて説明をしていきます。

保留中のデータの取得

ORDER_FILLEDFALSEのデータを取得します。

L.17
my_dataframe = session.table("smoothies.public.orders").filter(col("ORDER_FILLED")==0).collect()

データ取得結果に応じた処理

保留中のデータがあれば、データの編集が可能な表と送信ボタンを表示します。
今回は、ORDER_FILLEDのカラムのみ編集可能としたかったので、それ以外のカラムはオプションで編集不可に設定しています。
保留中のデータがない場合は、その旨メッセージを表示します。

L.19-39
if my_dataframe:
    editable_df = st.data_editor(my_dataframe,disabled=["ORDER_UID","NAME_ON_ORDER","INGREDIENTS","ORDER_TS"])
    submitted = st.button('送信')
...
...
else:
    st.success('現在、保留中の注文はありません', icon="👍")

送信ボタン押下時の処理1

送信ボタンがクリックされたら、現在のordersテーブルのデータと、アプリ上で編集されたデータを取得します。

L.23-26
    if submitted:
        
        og_dataset = session.table("smoothies.public.orders")
        edited_dataset = session.create_dataframe(editable_df)

送信ボタン押下時の処理2

ordersテーブルのORDER_FILLEDを編集された値へアップデートします。
mergeメソッドはSQLのMERGE文と同様に、キー(今回はORDER_UID)でマッチしたレコードに対して更新処理を行います。
失敗した場合は、メッセージを表示します。

L.23-36
    if submitted:
        ...
        try:
            og_dataset.merge(edited_dataset
                     , (og_dataset['ORDER_UID'] == edited_dataset['ORDER_UID'])
                     , [when_matched().update({'ORDER_FILLED': edited_dataset['ORDER_FILLED']})]
                    )

            st.success("注文が更新されました!", icon="👍")
        except:
            st.write('問題が発生しました')

https://docs.snowflake.com/ja/developer-guide/snowpark/reference/python/1.2.0/api/snowflake.snowpark.Table.merge#snowflake.snowpark.Table.merge

おわりに

今回は、StreamlitアプリからSnowflakeのデータを更新する方法を紹介しました。
ポイントは以下の2点です。

  • st.data_editorで編集可能なテーブルを簡単に作成できる
  • SnowparkのmergeメソッドでSQLを書かずにデータ更新ができる

StreamlitとSnowflakeの組み合わせは、Pythonだけでデータアプリを完結できるのが魅力です。
ぜひ皆さんも試してみてください!

Discussion