1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

NextremerAdvent Calendar 2019

Day 10

【MongoDB】APIログ取るのに手軽で最高だった件 (+intellijだとさらに手軽)

Last updated at Posted at 2020-02-13

#はじめに

気にはなっていたけど、なかなか触れる機会が無かった。。
そんな、同じクラスのあの子のような存在、それがmongoDBでした。
実際、使ってみると手軽でとても使いやすい。

こちらの記事では、簡単にインストールから導入までをまとめてみました。

#MongoDBを使った開発内容
趣味の個人開発でMongoDBを利用しました。
[APIを利用したbitcoin自動売買システム]

  • bitcoin値取得にCryptWatchAPIを使用
  • bitcoin売買にBitflyerAPIを使用
  • 開発言語:Node.js
  • 開発環境:macOS Catalina
  • デプロイ環境: AWS:EC2:ubuntu18.04LTS

MongoDBはbitcoin売買時の値段と、その売買判断に使われた値のログを取りたくて使用しました。

#mongoDBとは
誤解を恐れずに極端に言うと、

データをJSON形式でレコードできるデータベースです

すいません! ここでは、わかりやすさ優先しましたm(_ _)m
(玄人の方々、マサカリ投げないでください。)

他にも、
スケーラビリティ(拡張)しやすい、
スキーマレス(事前定義不要)である。 などなど、、ありますが、
詳しく知りたい方は以下のページをおすすめします。
詳しいオススメページ1
詳しいオススメページ2

#APIをレコードするのに最適!
mongoの特徴

  • スキーマレスで、
  • JSON形式

これが、APIを記録するのにすごく相性がいいです。
つまり、
APIからレスポンスされたJSONをそのままインサートすることができる!
さらに、
毎回APIの構造が変わってもそのままインサート可能!!
すごい楽ですね、
スキーマレスなので難しく考えず、ひとまず突っ込んで置くことができます。

これが、RDBMSだとどうなるか?

  • スキーマを細かく定義した上で、例外処理を施し構造が変わるものは省いてインサートする。
  • string,textとしてまるごとインサート

どちらも大変です。。
受け取る可能性のあるJSON内容を想定して、スキーマを細かく定義した上で、
処理は、レスポンスされたJSONをカラムに収まるように全部分解したり、例外処理を書いたり。。
2つ目は、まる投げでインサートすればいいのですが、columnがTEXT形式でも文字数制限あります。
mysqlだと最大長が65,535(216 − 1)文字になります。データを利用するときはまた、JSON形式に戻して。。
うぅ、吐きそうです(;´Д`)
しかも、ノード同士の構造を捨てちゃってます。

「今は何に使うかわかんないけどー、
あとで、面白いことに使いたいから、とりあえずサクッとデータ残しておこう♪」

こんなノリには、ぜひMongoDBです。

私のbitcoin売買システムも、
将来、趣味で分析したり、機械学習で回せたらオモロイだろうなーってノリだけです。
使えそうな値と、APIをまるごと、とりあえずインサートおく。
APIの構造が多少変わっても気にしない。

まずはその手軽さを触ってみることをオススメします。
それでは、簡単に導入方法をまとめます。

#インストール
##macOS
brewを使って、簡単にインストールできます。


brew install mongodb

#自動起動に設定
brew services start mongodb

##ubuntu18.04LTS
ubuntuはやや面倒です。
aptの管理ライブラリが最新のMongDBとなっていないため、
Mongoの公式から、パッケージを展開してインストールする必要があります。


#パッケージ管理システムに公開鍵を登録
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4

#ダウンロード用のリストファイルを作成
echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list

#パッケージ管理システムのデータベースをリロード
sudo apt-get update

#最新の安定版をインストール
sudo apt-get install -y mongodb-org

#MongoDBを自動起動にする
sudo systemctl enable mongod

#MongoDBを起動
sudo service mongod start

##raspbrerryPi
ラズパイにMongDBの最新バージョンはインストールできません。

正しくは、
ラズパイの公式OS:RasbianOSには、MongDB version2.4.14以上はインストールできません。

上記のMongoDBバージョンが、64bit対応のみとなっていますが、
RasbianOSが、32bitとなっているためです。

実は、ラズパイ自体は64bitのため
OSに引きづられて最新のMongoDBが利用できなくなっています。
ですので、OSを入れ替えたら使用できるかもしれません。
詳しくはこちら

mongo2.4以下だと、npmのmongoライブラリも対応していないため、
ラズパイでmongoDBを扱うのは特別な理由が無い限りあまりおすすめしないです。

#実装
##データベースの設定
ターミナルからmongoにデータベースを作成して、利用できるようにします。

# MongoDBに入る
mongo

# データベース切り替え、作成
use db_name

#データベースの確認
show dbs

#使用しているデータベースを確認
db

#コレクションの作成
db.createCollection("collect_name")

#コレクションを確認
show collections

#コレクションにドキュメントをインサート
db.collect_name.insertOne({ name: "hoge", age: 88})

#コレクション内のドキュメントを確認
db.collect_name.find()

# MongoDBから抜ける
exit

ちょっと説明

  • use db_name: データベースは無ければ、自動で作成されます。
  • collection: mongoではtableでは無く、collectionと言います。
  • document:mongoでは1つ1つのデータ(record)のことをdocumentと言います。

##コード実装
Node.jsで実装しました。
以下はベースの実装例です。


const MongoClient = require('mongodb').MongoClient;
const options = {
  useUnifiedTopology : true,
  useNewUrlParser : true
};
const url = 'mongodb://localhost:27017';
const dbName = 'db_name';

//即時関数と、asyncを定義
(async function () {
  let client;

  try {
    client = await MongoClient.connect(
        url,
        options,
    );
    //DB取得
    const db = client.db(dbName);

    //DBを操作
    await insertDoc(db);
    await findDoc(db);
  } catch (err) {
    //接続失敗
    console.log(err);
  }

  //接続を切る
  client.close();
})();

//Insert
function insertDoc(db) {
  const collection = db.collection('collect_name');
  collection.insertMany(
      [{ name: 'hoge', age: 88 }, { name: 'fuga', age: 14 }],
      (err, result) => {
        console.log('Success inserted');
      },
  );
}

//Find
function findDoc(db) {
  const collection = db.collection('collect_name');
  collection.find({}).toArray((err, docs) => {
        //検索内容をコンソール出力
        console.log(docs);
      });
}

#データ確認
bitcoinの売買データをmongoで取得してみました。

##標準のデータ確認

#terminalからの標準のデータ確認
{ 
"_id" : ObjectId("5df9c2ba73160d276ad2e3ad"), 
"flag" : "buy", 
"label" : "買い注文", 
"created_at" : ISODate("2019-12-18T06:10:02.072Z"), 
"strTime" : "2019/12/18 15:10:02", 
"price" : 737491, 
"shortMA" : 737293.825779211, 
"longMA" : 736227.9333333333, 
"countHigh" : 4, 
"records" : [ 735413, 735522, 735314, 735516, 735691, 735913, 736276, 736316, 736366, 736788, 736586, 736472, 735565, 735245, 735327, 735259, 735677, 735745, 736058, 736238, 736448, 736713, 736388, 736426, 736954, 737198, 736975, 737479, 737479, 737491 ] 
}

一部説明します

  • _id: mongoから自動で振られるid
  • created_at: ISODATE形式、datetime形式でinsertすることができます。
  • shortMA: 過去5回分のpriceの移動平均金額を算出
  • longMA: 過去30回分のpriceの移動平均金額を算出
  • records: 過去のpriceリスト。リスト形式でそのままinsertしています。

データの形式がlistでも、さらにツリーが入れ子状態になっても、insertすることができます。

##Intellij(jetBrains)を利用
CLIからだと、RDBMSよりも一覧性なくて見ずらいですね。データの閲覧はIDEや、ソフトをオススメします。
私は、IntelliJを使っています。
一度だけ接続設定をすれば、それ以後、ダブルクリックだけで、DBに接続してこのようにデータ閲覧できます。
ターミナルでコマンドを打つよりも、データ確認が手軽で早くて、見やすいです。

本来は上記のようなJSON形式のnodeツリーが、テーブル表示で一覧できます。
スクリーンショット 2020-02-12 13.54.32.png
クリックひとつでソートもできますし、絞り込みも簡単です。
ツリー形式での閲覧もできます。
スクリーンショット 2020-02-12 14.06.57.png

transposed table 日本語で何形式と言うのでしょう?こんな閲覧方法もできます。
スクリーンショット 2020-02-12 14.06.12.png

強いて不満を言えば、
table viewのとき、列の順番がバラバラとなるのが気になります。
(そもそもMongoDBにはDDLで読み取れるようなculumnの順番という概念がないのでしょうが無いです。)

#おわりに
MongDBは、お手軽で使い勝手がよいDBです。
APIデータを、今の時点ではどんな風に活用するか厳密に決めていないけど、
ひとまず導入しておいて後で考えるには、MongoDBは良い選択肢だと思います♪

最後までお読みいただきありがとうございました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?