ほぼ老人のプログラミング日記

定年後の平凡なサラリーマンの趣味の日記

Knowledge→GROWI 移行 (3)

Python で Knowledge のデータベース (PostgreSQL) にアクセスしてみる

PythonPostgreSQL にアクセスするする方法はさっぱり分かりませんから、いつものように Google で検索します。

たくさんヒットしますが、下記のサイトを参考にさせていただきました。

chusotsu-program.com

qiita.com

まずは、knowledges テーブルから knowledge_id と title を取り出してみます。全部取り出すと大変なので、条件をつけて 5 件だけ取り出します。

import psycopg2
from psycopg2.extras import DictCursor

# DB接続情報
DB_HOST = 'postgres'
DB_PORT = '5432'
DB_NAME = 'knowledgedb'
DB_USER = 'kbadmin'
DB_PASS = '**********'


# DB接続関数
def get_connection():
    return psycopg2.connect('postgresql://{user}:{password}@{host}:{port}/{dbname}'
                            .format(user=DB_USER, password=DB_PASS, host=DB_HOST, port=DB_PORT, dbname=DB_NAME))


with get_connection() as conn:
    with conn.cursor(cursor_factory=DictCursor) as cur:
        cur.execute('select knowledge_id, title from knowledges '
                    'where knowledge_id in (217, 227, 229, 236, 240)')
        for row in cur:
            print(str(row['knowledge_id']) + ' : ' + row['title'])

参考にさせてもらったサイトのサンプルを幾つか組み合わせただけです。取得した結果から列のデータを辞書式で取得したかったので、DictCursor を使いました。

結果はこんな感じです。

root@ced5581a8a4a:/workspace#  cd /workspace ; /usr/bin/env /usr/local/bin/python3.8 /root/.vscode-server/extensions/ms-python.python-2021.12.1559732655/pythonFiles/lib/python/debugpy/launcher 41367 -- /workspace/knowledge_to_growi/postgres_sample.py 
240 : Mac 関連のメモ
229 : Visual Studio Code 設定
227 : Docker
236 : POP3 サーバ内メールを取得して IMAP メールボックスに配信
217 : ORACLE メモ

続けて、添付ファイルを取得してみます。

        cur.execute('select file_no, knowledge_id, comment_no, draft_id, file_name, file_binary '
                    'from knowledge_files where file_no = 556')
        for row in cur:
            print(row['file_name'])
            file_name = './knowledge_to_growi/attachments/' \
                        + row['file_name']
            with open(file_name, 'wb') as f:
                f.write(row['file_binary'])

f:id:tiger62shin:20220131151018p:plain 添付ファイルもちゃんと取得できました。ところが、このままではちょっと問題があります。
私が実現したいのは「見出しや本文を取り出しつつ、その添付ファイルも取り出す」ことなので、上のコーディングだと cursor が 1 つしかないので knowledges から「見出し」や「本文」を一旦全部取り出してから、knowledge_files から添付ファイルを取り出すようにしないと上手くいかないと思います。それでもいいのですが、あまり好きな方法ではないので knowledges 用と knowledge_files 用の 2 つのカーソルを使います。ついでに目的の記事に添付されているファイルのみを取り出すようにします。

    with conn.cursor(cursor_factory=DictCursor) as knowledges_cur:
        knowledges_cur.execute('select knowledge_id, title from knowledges '
                               'where knowledge_id in (217, 227, 229, 236, 240)')
        for knowledge_row in knowledges_cur:
            print(str(knowledge_row['knowledge_id']) + ' : ' + knowledge_row['title'])

            with conn.cursor(cursor_factory=DictCursor) as file_cur:
                file_cur.execute('select file_no, knowledge_id, comment_no, draft_id, file_name, file_binary '
                                 'from knowledge_files '
                                 'where knowledge_id = %s', (knowledge_row['knowledge_id'], ))
                for file_row in file_cur:
                    print(file_row['file_name'])
                    file_name = './knowledge_to_growi/attachments/' + file_row['file_name']
                    with open(file_name, 'wb') as f:
                        f.write(file_row['file_binary'])

だいぶ、ネストが深くなりましたが、これで knowledges テーブルから記事を取り出しつつ、knowledge_files テーブルからその記事の添付ファイルを取り出すことが出来ました。
draft_knowledges からも同様の方法で取得できるはずです。


これで、GROWI に移行するデータを取得する目処がたちました。