素人が2020年までの1ヶ月でLINE BOTに挑戦する毎日note. 【Day 28:開発4日目_LINEログイン後にDBへデータを保存】

こんにちは。くろです。

12月1日から2019年残り1ヶ月でスケジュール調整BOTの開発に挑戦しています。今日は28日目です。

概要

開発アプリ:Googleカレンダーと連動してスケジュールを調整してくれるLINEBOT

BOTの概要:Day 2の記事に書いています。

BOTの仕様:機能一覧やフローチャート Day 10の記事に書いています。

BOTの開発環境:Day25の記事でアプリケーションの骨格を作りました。

昨日は「2,LINEログインしてマイページを表示する」のうちLINEログインの実装までを書きました。

今日はDBにユーザーデータを保存してDBへデータを保存する所まで書きます。

2-2,DBへユーザデータを保存

ちょっと前にherokuにpostgresqlというDBを接続しましたが、使い方がさっぱりなので、まずは学習からです。はやく開発したい、、、

調べているとどうやらSQL文というのを書ける必要があるみたいです。

heroku pg:psqlでherokuのpostgresqlにコマンドプロンプトからアクセスできる。その中でSQL文を叩くといろいろ実行できそうです。その後、\dって打てば、今あるTABLEの一覧が出てくるよう。

ただ、ここに打ってやっていくのか疑問はありますが、、、

SQLのコマンドはこの辺をざっと眺めておきました。

下記の2つの記事を組み合わせてデータベースを呼び出せるようにしました。

こんな感じにしてみました。

index.js

var { Client } = require('pg');
var connection = new Client({
 user: 'hogehoge',
 host: 'hogehoge',
 database: 'hogehoge',
 password: 'hogehoge',
 port: 5432
});

connection.connect()

ここまででpgというモジュールを使ってpostgresqlへ接続しています。

本当は別ファイルに入れたかったのですが、試行錯誤した結果ちょっと難しかったので、index.jsにいれてます。

hogehoge部分はherokuのpostgresqlのsetting>Database Credentialsの中にかいているやつをコピペです。

あ、これでもあれか環境変数に入れて読み出さないといけないな。とおもったので、変えました。

var { Client } = require('pg');
var connection = new Client({
 user: process.env.DB_USER,
 host: process.env.DB_HOST,
 database: process.env.DB_DATABASE,
 password: process.env.DB_PASSWORD,
 port: process.env.DB_PORT
});

connection.connect()

それぞれの環境変数をherokuの環境変数にいれました。

これで好きな所でconnection.query()を呼び出して、()の中にsql文を書けばいけそうなきがします。

まずはres.send(body)の後に、データベースへデータをインサート挿入するコードを書きます。

const linelogin_uid_insert = {
  text: 'INSERT INTO users (line_uid) VALUES($1)',
  values: [JSON.parse(body).userId],
}

connection.query(linelogin_uid_insert)
  .then(res => console.log("insert", res))
  .catch(e => console.error(e.stack))

実行してみると、テーブルがないって言われたので、テーブルを作るコードをインサートの前に入れます。

index.js

connection.query(db.create_table)
.then(res => console.log(res.rows[0]))
.catch(e => console.error(e.stack))

ここはなんとかがんばってdb.jsという別のファイルからcreate_tableを読み出すようにできました。db.jsに配列を書いて、それをindex.jsの上部で読み出しておくと、db.create_tableで呼び出すことができました。

index.js

const db = require('./routes/db');


db.js

//SQLで使う関数を書いていく
var create_table = {
   text: 'CREATE TABLE IF NOT EXISTS users (id SERIAL NOT NULL, line_uid VARCHAR(255) NOT NULL UNIQUE, google_id VARCHAR(255), display_name VARCHAR(255), created_at TIMESTAMP, updated_at TIMESTAMP, PRIMARY KEY (id))',
};

exports.create_table = create_table;

この時IF NOT EXISTSをいれないと、もうそのデータベースあるよって怒られます。これを入れると。usersっていうデータベースが存在している時は新しく作らないようになるので、回避できます。

また、idは行が増えるたびに勝手に1ずつ増やして番号をつけていって欲しいので、AutoIncrementというオプションをつけたのですが、これはmysqlでの仕様で、postgresqlでは使えないようでした。代わりに、オプションではなく、型をserial型にすると進めることができました。

AUTO_INCREMENTとは
カラムに値が指定されなかった場合、MySQLが自動的に値を割り当てる。
データ型は整数。
値は1ずつ増加して連番になる。

https://qiita.com/shonansurvivors/items/4522f15c5e9a30860bc5

最後にSELECTを入れてDBにデータが入っているか確認できるようにしました。res.row[0]で入れたデータが見れるっぽいんですが、ちょっとundefinedになってres.row[1]とかでも出なかったので、resだけコンソールで表示したらINSERTではこんな結果になってました。

command:	'INSERT'
rowCount:	1
oid:	0
rows:	[]
fields:	undefined
_parsers:	undefined
_types:	TypeOverrides
_types:	{
getTypeParser:	[Function:
setTypeParser:	[Function:
arrayParser:	[Object]
builtins:	[Object]
}	
text:	{}
binary:	{}
}	
RowCtor:	null
rowAsArray:	FALSE
}	

rowsの[]に何も入ってないからそらこやんわな。

逆にSELECTの方はちゃんとコンソールログにでてきましたし、コマンドプロンプトからheroku pg:psqlを叩いた後に、select * from users;を叩くと、しっかりDBに入ってました。3行あるのは3回試してしまったからです。

画像1

はいここで、お気づきの方もおられるかもしれませんが、同じuidやのに2個もidが作られると困りますよね、、、

そこを修正していきます。

が、ちょっと色々調べて、

// text: 'INSERT INTO users (line_uid) SELECT $1 AS VARCHAR WHERE NOT EXISTS (SELECT id FROM users WHERE line_uid = $1)',

こういうやつとかを試したんですが、ちょっと前に進まなくなったので、一旦usersテーブルを作る時にline_uidをUNIQUE設定にすることで、登録しようとするとエラーになるようにしておきました。本当は良くない気がするが、、

var create_table = {
   text: 'CREATE TABLE IF NOT EXISTS users (id SERIAL NOT NULL, line_uid VARCHAR(255) NOT NULL UNIQUE, google_id VARCHAR(255), created_at TIMESTAMP, updated_at TIMESTAMP, PRIMARY KEY (id))',
};

exports.create_table = create_table;

下記も進めたかったのですが、もろもろの修正ですごく時間を取られてしまったので、ちょっと明日に回させてもらいます。。。

やっぱり基礎をざっと学びたいな、、、

明日は

2-3,マイページ作成

2-4,DBからデータを取得してマイページに表示

をかきます。


・メモ

・pgのリファレンス


他のjsファイルのモジュールを呼び出す方法

データ型


この記事が参加している募集

よろしければサポートお願いします! 頂いたサポートはクリエイター活動に活用させて頂きます。