RaspberryPI + MongoDBを使う
MongoDBは、NoSQLデータベースと言われるのものです。
リレーショナルデータベースは、複数のテーブルを関連づけ高度な処理が可能となりますが、NoSQLデータベースは、非構造なデータを保管することが得意である反面、テーブル間の関連づけを持たないため、一貫性を持たせたい場合は、使う側が意識する必要があります。
様々なデータを保管していくならNoSQLの方が使い勝手はいいでしょう。
環境説明
まず、必要なパッケージは導入や、最低限のセキュリティや使い方を
学びましょう。
環境について
本環境は、別記事で導入した状態でスタートしています。
RaspberryPiのUbuntu環境です。こちらを参考にいただければと思います。
$ sudo apt list |grep mongodb-org
mongodb-org/bionic 4.4.18 amd64
$ python3 -V
Python 3.11.6
$ pip3 -V
pip 23.2 from /usr/lib/python3/dist-packages/pip (python 3.11)
$ mongo
MongoDB shell version v4.4.18
あと、Python 仮想環境として、venvで「flask」という環境を作っています。
<home dir>
└── app
└── flask ⭐️ python venv
MongoDBのユーザ作成
セキュリティ設定
MongoDBのパスワードは設定しておきましょう。
作成するユーザとして、「homeAdmin」を作っておきます。
データの追加・参照はこのユーザを使って進めます。
MongoDBユーザの作成
まず、mongoのコンソールを開きます。
$ mongo
MongoDB shell version v4.4.18
>
データベースを「admin」へ切り替え、ユーザを作成します。
$$
\begin{array}{|l|l|l|} \hline
user: & homeAdmin & 作成するユーザ名を指定\\ \hline
pwd: & passwordPrompt() & コマンド実行後にパスワード入力
\\ \hline
\end{array}
$$
> use admin
switched to db admin
> db.createUser(
{
user: "homeAdmin",
pwd: passwordPrompt(),
roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ]
}
)
MongoDBの設定
⭐️アカウントを作成しただけでは、認証機能は有効になりません。⭐️
コンフィグファイルの修正が必要です。
本環境では、コンフィグファイルの場所は、「/etc/mongod.conf」です。
わからない場合は「systemctl status mongod」 とかでも分かると思います。
$ systemctl status mongod
● mongod.service - MongoDB Database Server
Loaded: loaded (/lib/systemd/system/mongod.service; enabled; preset: enabled)
Active: active (running) since Mon 2024-03-11 13:10:44 JST; 19h ago
Docs: https://docs.mongodb.org/manual
Main PID: 3200 (mongod)
Memory: 191.2M
CPU: 16min 29.997s
CGroup: /system.slice/mongod.service
└─3200 /usr/bin/mongod --config /etc/mongod.conf ⭐️
Mar 11 13:10:44 raspi-01 systemd[1]: Started mongod.service - MongoDB Database Server.
「mongod.conf」ファイルを開き、「security」セクションのコメントアウトを
外し、「authorization: enabled」を追加します。
$ sudo nano /etc/mongod.conf
---------
security:
authorization: enabled
---------
編集が完了したら、データベースを再起動、起動していることを確認します。
$ sudo systemctl daemon-reload
$ sudo systemctl restart mongod
$ sudo systemctl status mongod
MongoDBへ接続する
設定が完了したら、MongoDBへ接続します。
「-u homeAdmin」を付け、ユーザを指定してログインします。
$ mongo -u homeAdmin
MongoDB shell version v4.4.18
Enter password:
connecting to: ・・・
Implicit session: session { "id" : UUID("・・・") }
MongoDB server version: 4.4.18
>
ユーザ情報の確認
ユーザは「admin」データベースに作成していますので、
「use admin」でデータベースを切り替え、「show users」で表示します。
> use admin
switched to db admin
> show users
{
"_id" : "admin.homeAdmin",
"userId" : UUID("・・・・"),
"user" : "homeAdmin", ⭐️
"db" : "admin",
"roles" : [
{
"role" : "userAdminAnyDatabase", ⭐️
"db" : "admin"
},
],
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
}
データを入れてみよう
データを入れないと何もできないので、データを投入します。
入れるデータは、Excelを使って作成していきます。
Excelでデータを作成する
Excelでデータを作成するのに意外と簡単な作成方法があります。
$$
\begin{array}{|l|l|l|} \hline
項目 & 内容 & 作成方法 \\ \hline
code & 連番 & フィルで作成 \\ \hline
name & 英字5文字 & RANDBETWEEN関数で作成 \\ \hline
price & 1-10000の範囲 & RANDBETWEEN関数で作成 \\ \hline
category & 英字1文字 & RANDBETWEEN関数で作成 \\ \hline
\end{array}
$$
name
= CHAR(RANDBETWEEN(65,90))&CHAR(RANDBETWEEN(65,90))&・・3回
CHAR(RANDBETWEEN(65,90))
・RANDBETWEEN(65,90)でA-Zの文字コードをランダムに返します。
・CHARでコードを文字に変換します。
price
=RANDBETWEEN(1,10000)
・1〜10000の間でランダム
category
=CHAR(RANDBETWEEN(65,70))
・nameと同じだが、文字をA-Fの5文字
作成したExcelデータを、CSVで保存します。
ヘッダ込みで120行作成しました。
PandasでCSV読み込み
作成したテストデータのCSVを一度pandasで読み込みます。
flask venv配下に「mongdb」を作成し、テストデータとmongo.pyを
保存しています。
./flask/mongodb/ ⭐️
├── mongo.py ⭐️
└── test.csv ⭐️
Pymongoのインストール
本記事では、Pymongoを使っていきます。
仮想環境をActivationして進めてください。
$ source flask/bin/activate
(flask) ~/app$ python3 -m pip install pymongo
mongo.pyの作成
コードを書いていきます。
1:import
・pandas , json , pymongoを読み込んでいます。
・MongoDBに入れる際は、JSON形式にしてあげる必要があります。
2:read_csv
・データフレームにCSVを読み込みます。CSVのフォーマット形式に注意して
ください。
3:DB接続
・MongoDBの接続情報を定義し接続します。先ほど作成した情報です。
4:JSON変換
・mongoDBにデータを入れるにはJson形式に変換が必要です。
5:MongoDB Insert
・DB: testdb、Collection:testlistにデータを入れます。
一括で入れるには、「insert_many」を使用します。
# 1:import
import pandas as pd
from pymongo import MongoClient
import json
# 2:pandasでCSVを読み込む
df = pd.read_csv('flask/mongodb/test.csv',encoding="utf-8")
# 3:MongoDB接続情報
target = 'localhost'
port = 27017
user = "homeAdmin"
passwd = "123Admin!"
# インスタンス作成
client = MongoClient(
target,
port,
username = user,
password = passwd
)
# 4:データフレームをjson形式に変換
records = json.loads(df.T.to_json()).values()
# 5:データ書き込み
# 以下の場所にデータを入れます。
# DB: testdb
# Collection:testlist
mycol = client.testdb.testlist
# 一括でデータを入れます。
mycol.insert_many(records)
# DBコネクションクローズ
client.close()
実行します。(print入れてなかったので何もなく完了します。)
(flask) app$ python3 flask/mongodb/mongo.py
データを見てみましょう
データベースの確認
登録したデータが、コレクションに入っているか見てみます。
・mongoDBに、ユーザを指定しログインします。
・show dbs で、データベースが作成されているか確認します。
・use testdb で、データベースを選択し、db.stats() で、「"collections" : 1,」コレクションが作成されていることを確認します。
・show collections で、コレクション名を確認します。
$ mongo -u homeAdmin
MongoDB shell version v4.4.18
Enter password:
MongoDB server version: 4.4.18
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
testdb 0.000GB
> use testdb
switched to db testdb
db.stats()
{
"db" : "testdb",
"collections" : 1,
"views" : 0,
"objects" : 119,
"avgObjSize" : 75,
"dataSize" : 8925,
"storageSize" : 20480,
"indexes" : 1,
"indexSize" : 20480,
"totalSize" : 40960,
"scaleFactor" : 1,
"fsUsedSize" : 6065352704,
"fsTotalSize" : 30900740096,
"ok" : 1
}
> show collections
testlist
データを出力する
読み込む場合は、find() で表示可能です。
> db.testlist.find()
{ "_id" : ObjectId("65efcc775dff9b65fc8141c3"), "code" : 1, "name" : "MCVKG", "price" : 3869, "category" : "F" }
{ "_id" : ObjectId("65efcc775dff9b65fc8141c4"), "code" : 2, "name" : "TLYJB", "price" : 5843, "category" : "C" }
{ "_id" : ObjectId("65efcc775dff9b65fc8141c5"), "code" : 3, "name" : "CQTWL", "price" : 2968, "category" : "E" }
{ "_id" : ObjectId("65efcc775dff9b65fc8141c6"), "code" : 4, "name" : "EWRTN", "price" : 4665, "category" : "C" }
{ "_id" : ObjectId("65efcc775dff9b65fc8141c7"), "code" : 5, "name" : "RWLIF", "price" : 7586, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc8141c8"), "code" : 6, "name" : "WJLFC", "price" : 3743, "category" : "C" }
{ "_id" : ObjectId("65efcc775dff9b65fc8141c9"), "code" : 7, "name" : "TSMUR", "price" : 2877, "category" : "F" }
(省略)
検索する
・find({ "code": 12 }) :上の行は、code:12を検索して表示しています。
・find({"category": "A"}):下の行は、category:Aを検索して表示しています。
きちんと動いている様ですね。
db.testlist.find({"code": 12})
{ "_id" : ObjectId("65efcc775dff9b65fc8141ce"), "code" : 12, "name" : "ROOCV", "price" : 5367, "category" : "C" }
> db.testlist.find({"category": "A"})
{ "_id" : ObjectId("65efcc775dff9b65fc8141c7"), "code" : 5, "name" : "RWLIF", "price" : 7586, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc8141cd"), "code" : 11, "name" : "KLTHY", "price" : 8441, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc8141d3"), "code" : 17, "name" : "YOGAI", "price" : 547, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc8141d5"), "code" : 19, "name" : "YEMTY", "price" : 4195, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc8141d8"), "code" : 22, "name" : "ADCXM", "price" : 4645, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc8141da"), "code" : 24, "name" : "WPZWK", "price" : 9601, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc8141e0"), "code" : 30, "name" : "RFCPL", "price" : 8509, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc8141eb"), "code" : 41, "name" : "LMEXV", "price" : 6289, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc8141ec"), "code" : 42, "name" : "LTJLT", "price" : 8780, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc8141fe"), "code" : 60, "name" : "AQXUQ", "price" : 4581, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc814206"), "code" : 68, "name" : "YPSGZ", "price" : 2020, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc81420a"), "code" : 72, "name" : "UXTPI", "price" : 3897, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc81420d"), "code" : 75, "name" : "QNLBO", "price" : 7117, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc814212"), "code" : 80, "name" : "YMLRR", "price" : 5055, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc814213"), "code" : 81, "name" : "ZBYOZ", "price" : 2207, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc814216"), "code" : 84, "name" : "QAZJT", "price" : 1038, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc814218"), "code" : 86, "name" : "JRLPC", "price" : 9224, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc81421c"), "code" : 90, "name" : "EVOOL", "price" : 6186, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc81421f"), "code" : 93, "name" : "XCXSV", "price" : 797, "category" : "A" }
{ "_id" : ObjectId("65efcc775dff9b65fc814221"), "code" : 95, "name" : "LXPGU", "price" : 6379, "category" : "A" }
pythonでデータを読み込んでみよう
やっとここまで辿り着きました。
pythonで今入れたデータを読み込んでみましょう。
read_mongo.py
データを読み込むための、pythonファイルを作成しました。
./flask/mongodb/
├── mongo.py
├── read_mongo.py 🌟
└── test.csv
基本的に、上部は先ほどの登録する時のコードと変わりません。
・.find()で全件を取得
・データフレームに変換
が変わっている点です。
# import
import pandas as pd
from pymongo import MongoClient
import json
# MongoDB接続情報
target = 'localhost'
port = 27017
user = "homeAdmin"
passwd = "123Admin!"
# インスタンス作成
client = MongoClient(
target,
port,
username = user,
password = passwd
)
# データ場所
# データの場所の指定。
# DB: testdb
# Collection:testlist
mycol = client.testdb.testlist
# 全件を取得します。
record = mycol.find()
# データフレームに変換します。
df = pd.DataFrame(record)
# 表示します。
print(df)
print(df.info())
実行します。
データを読み込み(119行)、データ欠損もない様です。
(flask) ~/app$ python3 ./flask/mongodb/read_mongo.py
_id code name price category
0 65efcc775dff9b65fc8141c3 1 MCVKG 3869 F
1 65efcc775dff9b65fc8141c4 2 TLYJB 5843 C
2 65efcc775dff9b65fc8141c5 3 CQTWL 2968 E
3 65efcc775dff9b65fc8141c6 4 EWRTN 4665 C
4 65efcc775dff9b65fc8141c7 5 RWLIF 7586 A
.. ... ... ... ... ...
114 65efcc775dff9b65fc814235 115 ZCDHJ 2234 D
115 65efcc775dff9b65fc814236 116 QEOPX 5097 E
116 65efcc775dff9b65fc814237 117 RTRRB 20 E
117 65efcc775dff9b65fc814238 118 EZDIZ 4884 E
118 65efcc775dff9b65fc814239 119 MUTRS 9609 B
[119 rows x 5 columns]
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 119 entries, 0 to 118
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 _id 119 non-null object
1 code 119 non-null int64
2 name 119 non-null object
3 price 119 non-null int64
4 category 119 non-null object
dtypes: int64(2), object(3)
memory usage: 4.8+ KB
None
Queryを追加してみましょう。
先ほどのコードにqueryを追加し、find(query)に変更しました。
mycol = client.testdb.testlist
# query
query = ({"code" : 12})
# 全件を取得します。
record = mycol.find(query)
# データフレームに変換します。
df = pd.DataFrame(record)
「code :12」だけが読み込めてますね。
pandasでフィルタしてもいいですが、DB側できちんと処理できていますね。
(flask) ~/app$ python3 ./flask/mongodb/read_mongo.py
_id code name price category
0 65efcc775dff9b65fc8141ce 12 ROOCV 5367 C
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1 entries, 0 to 0
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 _id 1 non-null object
1 code 1 non-null int64
2 name 1 non-null object
3 price 1 non-null int64
4 category 1 non-null object
dtypes: int64(2), object(3)
memory usage: 172.0+ bytes
None
お疲れ様でした。MongoDBでデータを扱える様になりました。
pythonとmongoを行ったり来たりしていますが、queryを書く際は、
mongoで検索結果を確認しながらの作業になるため、mongoでの操作も
記載しました。
ここから下は、データベースの削除、起動エラー、read_csvの文字コードなどを
書いています。基本的に調べたら分かることですが、わからない場合にご参考まで。
ここから先は
¥ 100
この記事が気に入ったらサポートをしてみませんか?