在 Windows 10 上安装 MongoDB 并从 Python 中使用
はじめに
为了准备使用 Azure Cosmos DB(文档+MongoDB API+Python),我重新审视了之前在手头整理的MongoDB信息。
MongoDB とは
MongoDBは、オープンソースのドキュメント指向データベース(NoSQL)です。
RDBMSのようにレコードをテーブルに格納するのではなく、「ドキュメント」と呼ばれる構造的データをJSONライクな形式で表現し、そのドキュメントの集合を「コレクション」として管理します。
最近では、様々な RDBMS が JSON を直接扱えるようになってきているので、MongoDB でなければならないというメリットはあまりないかもしれませんね。スケールの特徴というか目的に応じてといったところでしょうか。
Azure Cosmos DB 是什么?
Azure Cosmos DB は、ターンキーグローバル配布と透過的なマルチマスターレプリケーションを備えたフルマネージドデータベースサービスです。99パーセンタイルでの10ミリ秒未満の読み書き待機時間、世界規模のスループットとストレージの自動エラスティックスケーリング、99.999% の高可用性が実現し、明確に定義された5種類の整合性オプションが用意されています。これらはすべて、業界トップレベルの包括的な SLA の対象となります。
听说是这样的,大概是这个样子。
Azure Cosmos DB は、データの保存方式とAPIを選択できる分散データベース基盤で、データの保存方式は、Document、Graph、Key-Value の3つの NoSQL データモデルから選択できます。そして、それぞれのデータモデルで利用できる API を提供しています。
Azure Cosmos DB を使ってみるという目標に向けて、今回は MongoDB + PyMongo API + Python を試してみます。
環境
-
- Windows 10 Pro x64 1909
-
- Power Shell 6 x64
-
- Visual Studio Code 1.42.1 x64
-
- Python 3.7.6 x64
- Nodist 0.9.1 ( Node v12.16.0 ) Mongo Express 用
安装 MongoDB
-
- 下载MongoDB Community Server安装程序。
-
- 运行下载的安装程序(例如:mongodb-win32-x86_64-2012plus-4.2.3-signed.msi)。
-
- 选择[自定义设置],指定安装路径(例如:D:\Develop\Bin\MongoDB\Server\4.2\)。
-
- 勾选[安装为服务(MongoD)]选项并继续。(以Windows服务的方式注册)
-
- 勾选[安装MongoDB Compass]选项并继续。(MongoDB的图形用户界面CRUD工具)
- 进行安装。
MongoDB 的配置设置
将MongoDB的路径添加到环境变量中。
-
- 将MongoDB的“bin”目录(例如:D:\Develop\Bin\MongoDB\Server\4.2\bin)添加到PATH中。
确认MongoDB的PATH设置成功。
> Get-PSDrive
> Set-Location Env:
> Get-ChildItem | Where-Object { $_.Name -eq ‘Path’ } | Format-List
如果没有勾选“Install MongoDB as a Service”(选项1),
手动创建data目录和logs目录,并确认MongoDB已经启动。
-
- 在安装目录下创建一个用于数据库的”data”目录和一个用于日志的”logs”目录。
> cd D:\Develop\Bin\MongoDB\Server\4.2
> mkdir data
> mkdir logs
检查MongoDB是否已启动。
> mongod –dbpath D:\Develop\Bin\MongoDB\Server\4.2\data –logpath D:\Develop\Bin\MongoDB\Server\4.2\mongod.log
使用netstat命令检查端口。(默认端口:27017)
> Get-NetTCPConnection | Where-Object { $_.LocalPort -eq 27017 -or $_.RemotePort -eq 27017 }
> Get-NetTCPConnection -LocalPort 27017(此命令也可以)
ユーザーの登録・更新・削除
MongoDBが起動している状態で、ユーザーの登録を行います。
> mongo
> use admin
> db.createUser( { user:”admin”, pwd:”password”, roles:[{ “role” : “root”, “db” : “admin” }] } );
> use test
> db.createUser( { user:”hoge”, pwd:”password”, roles:[{ “role” : “dbOwner”, “db” : “test” }] } );
> db.createUser( { user:”fuga”, pwd:”password”, roles:[{ “role” : “readWrite”, “db” : “test” }] } );
> exit
ユーザーを確認します。
> mongo
> use admin
> db.system.users.find();
> exit
ユーザーを更新します。
> use test
> db.updateUser( “hoge”, { roles:[{ “role” : “readWrite”, “db” : “test” }] } );
参考までにユーザー削除。
> use admin
> db.system.users.remove( { “_id” : “admin” } );
如果没有选中”将MongoDB安装为服务”(第2部分)
以手动方式创建mongod.conf文件,并将MongoDB注册为服务。
-
- ユーザーを登録したら「Ctrl+C」でMongoDBを終了します。
インストールディレクトリの mongod.cfg ファイルを編集します。
> cd D:\Develop\Bin\MongoDB\Server\4.2\bin
> code mongod.cfg
mongod.cfg ファイルに下記内容を記述します。
storage:
dbPath: D:\Develop\Bin\MongoDB\Server\4.2\data
journal:
enabled: true
systemLog:
destination: file
logAppend: true
path: D:\Develop\Bin\MongoDB\Server\4.2\log\mongod.log
net:
port: 27017
bindIp: 127.0.0.1
security:
authorization: enabled
auth=trueで認証を有効にしています。そのために事前にユーザーを登録しています。
「mongod.cfg」ファイルを指定してWindowsサービスとして登録します。(管理者として実行)
> mongod –config “D:\Develop\Bin\MongoDB\Server\4.2\bin\mongod.cfg” –install –serviceName MongoDB
サービスとして登録しない場合は「–install」を指定しません。
参考までにサービス削除。(サービスが停止している状態で実行)
> mongod –remove
启动和停止MongoDB服务
-
- コントロールパネル – 管理ツール – サービス にMongoDBが登録されていることを確認します。
netコマンドを利用してサービスの開始と停止を制御できます。(管理者として実行)
> net start MongoDB
> net stop MongoDB
使用MongoDB
MongoDB のコマンドラインクライアントが起動できることを確認します。
> mongo
exitでコマンドラインクライアントを終了できます。
認証を必要としている(認証していない)場合は、以下のコマンドで認証します。
> use test
> db.auth(“hoge”, “password”);
MongoDB のコマンドラインクライアントを起動する際に指定することもできます。
adminユーザーの場合はadminデータベースを指定する必要があることに注意します。
> mongo [ホスト名:ポート番号/DB名] -u [ユーザー名] -p
> mongo localhost:27017/test -u hoge -p
> mongo localhost:27017/admin -u admin -p
> mongo [DB名] -u [ユーザー名] -p
> mongo test -u hoge -p
データベースの一覧を表示します。
> show dbs
データベースを作成します。
> use test
データベースを切り替えます。
> use test
データベースを削除します。
> use test
> db.dropDatabase();
コレクション(テーブル)の一覧を表示します。
> use test
> show collections
コレクション(テーブル)を作成します。
> use test
> db.createCollection(“[コレクション名]”);
コレクション(テーブル)を削除します。
> use test
> db.[コレクション名].drop();
ドキュメント(レコード)を追加します。
> db.things.save( {“name”:”Taro”, “age”:36} );
ドキュメント(レコード)の一覧を表示します。
> db.things.find();
> db.things.find({name: “Taro”});
ドキュメント(レコード)を更新します。
> db.things.update( {“name”:”Taro”, “age”:36}, {“name”:”Jiro”, “age”:18} );
ドキュメント(レコード)内の数値を加算します。
> db.things.update( {“name”:”Jiro”, “age”:18}, { $inc : {“age”:1} } );
ドキュメント(レコード)を削除します。
> db.things.remove( {“name”:”Jiro”} );
JavaScriptを利用することもできます。
> for (var i = 0; i < 1000000; i++) { db.things.save( {“name”:”Xxxx”, “age”:i} ); } インデックスを設定します。 > db.bench.ensureIndex({age:1}, {unique: true});
Mongo-Express 的使用(参考)
我們將使用mongo-express來在網頁瀏覽器上管理MongoDB。
最近常用的是使用 MongoDB Compass 的基于 Node.js 和 Express 创建的 Web 管理界面。
mongo-expressをインストールします。
> npm install -g mongo-express
mongo-expressのディレクトリに移動します。
> cd D:\Develop\Bin\Nodist\bin\node_modules\mongo-express
config.default.js をコピーして config.js を作成します。
> cp config.default.js config.js
> code config.js
config.js を編集します。
// 必要に応じてラベルを修正します。
var dbLabel = ‘mongodb-2.4’;
↓
var dbLabel = ‘mongodb-4.2’;
// adminでの利用を強制します。
admin: process.env.ME_CONFIG_MONGODB_ENABLE_ADMIN ? process.env.ME_CONFIG_MONGODB_ENABLE_ADMIN.toLowerCase() === ‘true’ : false,
↓
admin: true,
// adminでの利用のため空指定とします。(ユーザーとDBを固定とした場合はそのDBのみ利用可能となります。)
auth: [
{
database: process.env.ME_CONFIG_MONGODB_AUTH_DATABASE || mongo.db,
username: getFileEnv(dbAuthUsername) || mongo.username,
password: getFileEnv(dbAuthPassword) || mongo.password,
},
],
↓
auth: [],
// adminのユーザー名とパスワードを指定します。
adminUsername: getFileEnv(adminUsername) || ”,
adminPassword: getFileEnv(adminPassword) || ”,
↓
adminUsername: getFileEnv(adminUsername) || ‘admin’,
adminPassword: getFileEnv(adminPassword) || ‘password’,
// BASIC認証のユーザー名とパスワードを指定します。
basicAuth: {
username: getFileEnv(basicAuthUsername) || ‘admin’,
password: getFileEnv(basicAuthPassword) || ‘pass’,
},
↓
basicAuth: {
username: getFileEnv(basicAuthUsername) || ‘hoge’,
password: getFileEnv(basicAuthPassword) || ‘password’,
},
mongo-expressを起動します。
> node app.js
ブラウザを起動し、http://localhost:8081 にアクセスするとページが表示されます。
config.jsで指定したBASIC認証のユーザー名とパスワードを用いてアクセスします。
ポート番号はconfig.jsで指定したものです。
Ctrl + C で停止します。
将mongo-express永久运行为守护进程(参考)
让我们将mongo-express转化为守护进程并执行试试看。
要将像 mongo-express 这样的 Node.js 应用程序Daemon化,可以使用 forever。
-
- 永久にインストールします。
> npm install -g forever
デーモン化するために、mongo-expressの起動に使用していたnodeをforeverに変更します。
> forever start app.js
実行中のデーモンプロセスをリストアップします。
> forever list
実行中のデーモンプロセスを停止します。
> forever stop [uid(4桁の英数字)]
使用MongoDB Compass
我将尝试使用MongoDB的GUI CRUD工具。
使用MongoDB Compass作为MongoDB的图形用户界面,可以更明智地做出关于文档结构、查询、索引创建、文档验证等方面的决策。
-
- 启动MongoDB Compass。
在“New Connection”中输入连接信息,然后点击“CONNECT”。
格式
mongodb://[用户名:密码@]主机1[:端口1][,…主机N[:端口N]][/[数据库][?选项]]
admin连接示例
mongodb://admin:密码@localhost:27017/admin
连接成功后,将显示MongoDB的数据库。
点击屏幕底部的“+”可以创建数据库和集合。
选择数据库后,将显示MongoDB的集合。
可以使用JSON文件或CSV文件导入集合中的数据。
使用Python和PyMongo对MongoDB进行示例使用
我将使用Python和PyMongo创建一个使用示例程序。
创建项目目录
> mkdir mongo_sample
> cd mongo_sample
建立Python虚拟环境
使用 virtualenv 建立并激活虚拟环境。
> virtualenv venv
> activate
安装 PyMongo 和 pprint
(venv) > pip install pymongo
(venv) > pip install pprint
编写程序
创建一个名为 main.py 的文件。
(venv) > ni main.py
我們為MongoDB準備了一個使用示例程式。
from pymongo import MongoClient
from bson.objectid import ObjectId
import pprint
import os
# データベースへの接続
client = MongoClient("mongodb://localhost:27017/")
# データベースの取得
db = client.test
# 認証
db.authenticate(name="hoge",password="password")
# コレクションの取得
users = db.users
# コレクションへ単一ドキュメントを挿入
print("コレクションへ単一ドキュメントを挿入")
new_user = {"name":"Taro", "age":36}
user_id = users.insert_one(new_user).inserted_id
# コレクションから単一ドキュメントを取得(条件なし)
print("コレクションから単一ドキュメントを取得(条件なし)")
user = users.find_one()
pprint.pprint(user)
# コレクションから単一ドキュメントを取得(条件指定:名前=Taro)
print("コレクションから単一ドキュメントを取得(条件指定:名前=Taro)")
user = users.find_one({"name": "Taro"})
pprint.pprint(user)
# コレクションから単一ドキュメントを取得(条件指定:_id)
print("コレクションから単一ドキュメントを取得(条件指定:_id)")
user = users.find_one({"_id": user_id})
pprint.pprint(user)
# コレクションから単一ドキュメントを取得(条件指定:文字列のIDを_idに変換)
# Webアプリのクエリパラメータから取得したIDを使用する場合などは変換が必要
print("コレクションから単一ドキュメントを取得(条件指定:文字列のIDを_idに変換)")
string_id = str(user_id)
user = users.find_one({"_id": ObjectId(string_id)})
pprint.pprint(user)
# コレクションへ複数ドキュメントを挿入(5件)
print("コレクションへ複数ドキュメントを挿入(5件)")
new_users = [{"name":"Hoge", "age":19},
{"name":"Fuga", "age":32},
{"name":"Moge", "age":27},
{"name":"Page", "age":38},
{"name":"Nazo", "age":35}]
result = users.insert_many(new_users)
pprint.pprint(result.inserted_ids)
# コレクションから複数ドキュメントを取得(全件)
print("コレクションから複数ドキュメントを取得(全件)")
for user in users.find():
pprint.pprint(user)
# コレクションの単一ドキュメントを更新(条件指定:_id、年齢を18に更新)
print("コレクションの単一ドキュメントを更新(条件指定:_id、年齢を18に更新)")
users.update_one({"_id": user_id}, {"$set": {"age":18}})
for user in users.find():
pprint.pprint(user)
# コレクションの複数ドキュメントを更新(条件指定:年齢<20、年齢に3を加算)
print("コレクションの複数ドキュメントを更新(条件指定:年齢<20、年齢に3を加算)")
users.update_many({'age': {"$lt": 20}}, {'$inc': {'age': 3}})
for user in users.find():
pprint.pprint(user)
# コレクションから単一ドキュメントを削除(条件指定:_id)
print("コレクションから単一ドキュメントを削除(条件指定:_id)")
users.delete_one({"_id": user_id})
for user in users.find():
pprint.pprint(user)
# コレクションから複数ドキュメントを削除(条件指定:年齢>=30)
print("コレクションから複数ドキュメントを削除(条件指定:年齢>=30)")
users.delete_many({'age': {"$gte": 30}})
for user in users.find():
pprint.pprint(user)
# コレクションから複数ドキュメントを取得(条件指定:名前=Moge)
print("コレクションから複数ドキュメントを取得(条件指定:名前=Moge)")
for user in users.find({"name": "Moge"}):
pprint.pprint(user)
# コレクションから複数ドキュメントを取得(条件指定:年齢<30)
print("コレクションから複数ドキュメントを取得(条件指定:年齢<30)")
for user in users.find({"age": {"$lt": 30}}).sort("age"):
pprint.pprint(user)
# コレクションのドキュメント件数を取得
print("コレクションのドキュメント件数を取得")
count = users.count_documents({})
print(count)
执行程序
执行 main.py 文件。
(venv) > python main.py
执行结果 (shí jié guǒ)
コレクションへ単一ドキュメントを挿入
コレクションから単一ドキュメントを取得(条件なし)
{'_id': ObjectId('5e5740368d00d876059ce6f2'), 'age': 36, 'name': 'Taro'}
コレクションから単一ドキュメントを取得(条件指定:名前=Taro)
{'_id': ObjectId('5e5740368d00d876059ce6f2'), 'age': 36, 'name': 'Taro'}
コレクションから単一ドキュメントを取得(条件指定:_id)
{'_id': ObjectId('5e5740368d00d876059ce6f2'), 'age': 36, 'name': 'Taro'}
コレクションから単一ドキュメントを取得(条件指定:文字列のIDを_idに変換)
{'_id': ObjectId('5e5740368d00d876059ce6f2'), 'age': 36, 'name': 'Taro'}
コレクションへ複数ドキュメントを挿入(5件)
[ObjectId('5e5740378d00d876059ce6f3'),
ObjectId('5e5740378d00d876059ce6f4'),
ObjectId('5e5740378d00d876059ce6f5'),
ObjectId('5e5740378d00d876059ce6f6'),
ObjectId('5e5740378d00d876059ce6f7')]
コレクションから複数ドキュメントを取得(全件)
{'_id': ObjectId('5e5740368d00d876059ce6f2'), 'age': 36, 'name': 'Taro'}
{'_id': ObjectId('5e5740378d00d876059ce6f3'), 'age': 19, 'name': 'Hoge'}
{'_id': ObjectId('5e5740378d00d876059ce6f4'), 'age': 32, 'name': 'Fuga'}
{'_id': ObjectId('5e5740378d00d876059ce6f5'), 'age': 27, 'name': 'Moge'}
{'_id': ObjectId('5e5740378d00d876059ce6f6'), 'age': 38, 'name': 'Page'}
{'_id': ObjectId('5e5740378d00d876059ce6f7'), 'age': 35, 'name': 'Nazo'}
コレクションの単一ドキュメントを更新(条件指定:_id、年齢を18に更新)
{'_id': ObjectId('5e5740368d00d876059ce6f2'), 'age': 18, 'name': 'Taro'}
{'_id': ObjectId('5e5740378d00d876059ce6f3'), 'age': 19, 'name': 'Hoge'}
{'_id': ObjectId('5e5740378d00d876059ce6f4'), 'age': 32, 'name': 'Fuga'}
{'_id': ObjectId('5e5740378d00d876059ce6f5'), 'age': 27, 'name': 'Moge'}
{'_id': ObjectId('5e5740378d00d876059ce6f6'), 'age': 38, 'name': 'Page'}
{'_id': ObjectId('5e5740378d00d876059ce6f7'), 'age': 35, 'name': 'Nazo'}
コレクションの複数ドキュメントを更新(条件指定:年齢<20、年齢に3を加算)
{'_id': ObjectId('5e5740368d00d876059ce6f2'), 'age': 21, 'name': 'Taro'}
{'_id': ObjectId('5e5740378d00d876059ce6f3'), 'age': 22, 'name': 'Hoge'}
{'_id': ObjectId('5e5740378d00d876059ce6f4'), 'age': 32, 'name': 'Fuga'}
{'_id': ObjectId('5e5740378d00d876059ce6f5'), 'age': 27, 'name': 'Moge'}
{'_id': ObjectId('5e5740378d00d876059ce6f6'), 'age': 38, 'name': 'Page'}
{'_id': ObjectId('5e5740378d00d876059ce6f7'), 'age': 35, 'name': 'Nazo'}
コレクションから単一ドキュメントを削除(条件指定:_id)
{'_id': ObjectId('5e5740378d00d876059ce6f3'), 'age': 22, 'name': 'Hoge'}
{'_id': ObjectId('5e5740378d00d876059ce6f4'), 'age': 32, 'name': 'Fuga'}
{'_id': ObjectId('5e5740378d00d876059ce6f5'), 'age': 27, 'name': 'Moge'}
{'_id': ObjectId('5e5740378d00d876059ce6f6'), 'age': 38, 'name': 'Page'}
{'_id': ObjectId('5e5740378d00d876059ce6f7'), 'age': 35, 'name': 'Nazo'}
コレクションから複数ドキュメントを削除(条件指定:年齢>=30)
{'_id': ObjectId('5e5740378d00d876059ce6f3'), 'age': 22, 'name': 'Hoge'}
{'_id': ObjectId('5e5740378d00d876059ce6f5'), 'age': 27, 'name': 'Moge'}
コレクションから複数ドキュメントを取得(条件指定:名前=Moge)
{'_id': ObjectId('5e5740378d00d876059ce6f5'), 'age': 27, 'name': 'Moge'}
コレクションから複数ドキュメントを取得(条件指定:年齢<30)
{'_id': ObjectId('5e5740378d00d876059ce6f3'), 'age': 22, 'name': 'Hoge'}
{'_id': ObjectId('5e5740378d00d876059ce6f5'), 'age': 27, 'name': 'Moge'}
コレクションのドキュメント件数を取得
2
总结来说
我已经很久没有使用MongoDB了,但是如果是简单的实现,应该没有问题。
能够轻松地保存文档确实很好。
下次我打算尝试使用Azure Cosmos DB。