今日はなにの日。

気になったこと勉強になったことのメモ。

今日は、MongoDB入門してRDBとの違いを感じたの日。

目次

とある日

MongoDBを触ってみたいと思ったので試しに検証しました際に、RDBと比べて違った点があったのでまとめます。

チュートリアル

構築

↓こちらの記事を参考にDocker-composeで構築しました。

docker-composeでmongoDB環境を構築して使う - Qiita

# Use root/example as user/password credentials
version: '3.1'

services:

  mongo:
    image: mongo
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: password

  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - 8081:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: root
      ME_CONFIG_MONGODB_ADMINPASSWORD: password
      ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo:27017/

mongo-expressGUIのやつなので(phpmyadminみたいな)いらないかなと後で思いました。

Dockerのimageが公式で用意されているので簡単に構築できます。

接続

C:\Users\Documents\GitHub\Docker\Docker-compose\MongoDB>docker-compose up -d
[+] Running 20/20
 - mongo-express Pulled                                                                                              16.4s
   - 6a428f9f83b0 Pull complete                                                                                       4.9s
   - f2b1fb32259e Pull complete                                                                                       8.7s
   - 40888f2a0a1f Pull complete                                                                                       8.9s
   - 4e3cc9ce09be Pull complete                                                                                       8.9s
   - eaa1898f3899 Pull complete                                                                                       9.1s
   - ab4078090382 Pull complete                                                                                      11.0s
   - ae780a42c79e Pull complete                                                                                      11.1s
   - e60224d64a04 Pull complete                                                                                      11.2s
 - mongo Pulled                                                                                                      24.7s
   - 7b1a6ab2e44d Pull complete                                                                                       4.1s
   - 90eb44ebc60b Pull complete                                                                                       4.2s
   - 5085b59f2efb Pull complete                                                                                       4.5s
   - c7499923d022 Pull complete                                                                                       4.9s
   - 019496b6c44a Pull complete                                                                                       5.0s
   - c0df4f407f69 Pull complete                                                                                       5.1s
   - 351daa315b6c Pull complete                                                                                       5.1s
   - a233e6240acc Pull complete                                                                                      19.5s
   - a3f57d6be64f Pull complete                                                                                      19.5s
   - dd1b5b345323 Pull complete                                                                                      19.6s
[+] Running 3/3
 - Network mongodb_default            Created                                                                         0.1s
 - Container mongodb_mongo_1          Started                                                                         0.7s
 - Container mongodb_mongo-express_1  Started                                                                         0.8s

C:\Users\Documents\GitHub\Docker\Docker-compose\MongoDB>docker-compose ps
NAME                      COMMAND                  SERVICE             STATUS              PORTS    
mongodb_mongo-express_1   "tini -- /docker-ent…"   mongo-express       restarting
mongodb_mongo_1           "docker-entrypoint.s…"   mongo               running             27017/tcp

C:\Users\Documents\GitHub\Docker\Docker-compose\MongoDB>docker-compose exec mongo bash
root@ae2f058f0f67:/# ll
total 172
drwxr-xr-x   1 root root   4096 Dec 27 21:53 ./
drwxr-xr-x   1 root root   4096 Dec 27 21:53 ../
-rwxr-xr-x   1 root root      0 Dec 27 21:53 .dockerenv*
lrwxrwxrwx   1 root root      7 Oct  6 16:47 bin -> usr/bin/
drwxr-xr-x   2 root root   4096 Apr 15  2020 boot/
drwxr-xr-x   4 root root   4096 Dec  8 00:25 data/
drwxr-xr-x   5 root root    340 Dec 27 21:53 dev/
drwxr-xr-x   2 root root   4096 Oct 16 03:04 docker-entrypoint-initdb.d/
drwxr-xr-x   1 root root   4096 Dec 27 21:53 etc/
drwxr-xr-x   2 root root   4096 Apr 15  2020 home/
-rw-r--r--   1 root root 108975 Oct 16 03:04 js-yaml.js
lrwxrwxrwx   1 root root      7 Oct  6 16:47 lib -> usr/lib/
lrwxrwxrwx   1 root root      9 Oct  6 16:47 lib32 -> usr/lib32/        
lrwxrwxrwx   1 root root      9 Oct  6 16:47 lib64 -> usr/lib64/        
lrwxrwxrwx   1 root root     10 Oct  6 16:47 libx32 -> usr/libx32/      
drwxr-xr-x   2 root root   4096 Oct  6 16:47 media/
drwxr-xr-x   2 root root   4096 Oct  6 16:47 mnt/
drwxr-xr-x   2 root root   4096 Oct  6 16:47 opt/
dr-xr-xr-x 320 root root      0 Dec 27 21:53 proc/
drwx------   1 root root   4096 Oct 16 03:04 root/
drwxr-xr-x   5 root root   4096 Oct  6 16:58 run/
lrwxrwxrwx   1 root root      8 Oct  6 16:47 sbin -> usr/sbin/
drwxr-xr-x   2 root root   4096 Oct  6 16:47 srv/
dr-xr-xr-x  11 root root      0 Dec 27 21:53 sys/
drwxrwxrwt   1 root root   4096 Dec 27 21:53 tmp/
drwxr-xr-x   1 root root   4096 Dec  8 00:24 usr/
drwxr-xr-x   1 root root   4096 Oct  6 16:58 var/
root@ae2f058f0f67:/# 
root@ae2f058f0f67:/# mongo admin -u root -p
MongoDB shell version v5.0.5
Enter password: 
connecting to: mongodb://127.0.0.1:27017/admin?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("65ed13ad-a7d8-4eae-aebb-f9c5a3717090") }
MongoDB server version: 5.0.5
================
Warning: the "mongo" shell has been superseded by "mongosh",
which delivers improved usability and compatibility.The "mongo" shell has been deprecated and will be removed in
an upcoming release.
For installation instructions, see
https://docs.mongodb.com/mongodb-shell/install/
================
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
        https://docs.mongodb.com/
Questions? Try the MongoDB Developer Community Forums
        https://community.mongodb.com
---
The server generated these startup warnings when booting:
        2021-12-27T21:53:04.025+00:00: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine. See http://dochub.mongodb.org/core/prodnotes-filesystem
        2021-12-27T21:53:05.284+00:00: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. We suggest setting it to 'never'
---
---
        Enable MongoDB's free cloud-based monitoring service, which will then receive and display
        metrics about your deployment (disk utilization, CPU, operation statistics, etc).

        The monitoring data will be available on a MongoDB website with a unique URL accessible to you
        and anyone you share the URL with. MongoDB may use this information to make product
        improvements and to suggest MongoDB products and deployment options to you.

        To enable free monitoring, run the following command: db.enableFreeMonitoring()
        To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
---
> show databases
admin   0.000GB
config  0.000GB
local   0.000GB

データ挿入

> use test2
switched to db test2
> db.hoge.insert({ name: "test" })
WriteResult({ "nInserted" : 1 })
> db.hoge.find()
{ "_id" : ObjectId("61ca36c635b01c7a00ba15ce"), "name" : "test" }
> db
test2
> db.people.insertOne( {
...     user_id: "abc123",
...     age: 55,
...     status: "A"
...  } )
{
        "acknowledged" : true,
        "insertedId" : ObjectId("61ca37f735b01c7a00ba15cf")
}
> db.hoge.find()
{ "_id" : ObjectId("61ca36c635b01c7a00ba15ce"), "name" : "test" }
> db.people.find()
{ "_id" : ObjectId("61ca37f735b01c7a00ba15cf"), "user_id" : "abc123", "age" : 55, "status" : "A" }
> db
test2
> table
uncaught exception: ReferenceError: table is not defined :
@(shell):1:1
> show collections;
hoge
people
> db.createCollection('test');
{ "ok" : 1 }
> show collections;
hoge
people
test
> db.test.find()
> db.tst.find()
> db.system.users.find();
> 
> db.system.users.find();
> use admin
switched to db admin
> db.system.users.find();
{ "_id" : "admin.root", "userId" : UUID("cae1fa15-67cc-4e42-b17a-84eae27d923e"), "user" : "root", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "wdpPednmfmpH/3PpafI1Qg==", "storedKey" : "ILk3afygYIYTP/n7UMipZ4ExhD4=", "serverKey" : "9+CNpNgfLmQhCE49ZK3MwXoaG4w=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "XeA8Xk9A4CXgHPj+kDcMswaVx1a8HSLnM0I3fQ==", "storedKey" : "ZJ9vl+pM9yZq1J3zTONN/TyZ1EXTkztBR2ny5nSHdIM=", "serverKey" : "XUytDm5LQwNO9po0amT671sOLyRjsXocvrNoqov3VvQ=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] }
>

RDBとの操作的違い

用語

RDBはテーブルと言うがNoSQLとかはコネクションっていうらしい。

SQL to MongoDB Mapping Chart — MongoDB Manual

SQL Terms/Concepts MongoDB Terms/Concepts
database database
table collection
row document or BSON document
column field
index index

コネクションとテーブルの振る舞い

ないコネクションにfindした際、データがない場合とコネクションがない場合の結果が同じで、コネクション名のミスに気づかなそうだなと。

MongoDBコマンド一覧(自分用メモ) - Qiita

> show collections;
hoge
people
test
> db.test.find()
> db.tst.find()

オペレーションの作成

作成または挿入操作は、コレクションに新しいドキュメントを追加します。コレクションが現在存在しない場合、挿入操作によってコレクションが作成されます。

それの原因は、生成されるタイミングが違うかららしい。

CUIの振る舞い

MySQLとかのRDBMSだとコロン打つまで入力が続くが、MongoDBだとそこらへんよしなに判断してくれるみたい。これは便利。

> db.hoge.insert({ name: "test" }
... )
WriteResult({ "nInserted" : 1 })

補完も効くので便利だなと思いました。

> db
DBCommandCursor(  DBExplainQuery(   DBPointer(        db
> db.
Display all 102 possibilities? (y or n)
db.adminCommand(                   db.getMongo(                       db.printShardingStatus(
db.aggregate(                      db.getName(                        db.printSlaveReplicationInfo(
db.auth(                           db.getProfilingLevel(              db.propertyIsEnumerable
db.changeUserPassword(             db.getProfilingStatus(             db.prototype
db.commandHelp(                    db.getQueryOptions(                db.removeUser(
db.constructor                     db.getReplicationInfo(             db.revokePrivilegesFromRole(
db.createCollection(               db.getRole(                        db.revokeRolesFromRole(
db.createRole(                     db.getRoles(                       db.revokeRolesFromUser(
db.createUser(                     db.getSecondaryOk(                 db.rotateCertificates(
db.createView(                     db.getSession(                     db.runCommand(
db.currentOP(                      db.getSiblingDB(                   db.runCommandWithMetadata(
db.currentOp(                      db.getSisterDB(                    db.runReadCommand(
db.currentOpCursor(                db.getSlaveOk(                     db.serverBits(
db.currentOpLegacy(                db.getUser(                        db.serverBuildInfo(
db.dbEval(                         db.getUsers(                       db.serverCmdLineOpts(
db.disableFreeMonitoring(          db.getWriteConcern(                db.serverStatus(
db.dropAllRoles(                   db.grantPrivilegesToRole(          db.setLogLevel(
db.dropAllUsers(                   db.grantRolesToRole(               db.setProfilingLevel(
db.dropDatabase(                   db.grantRolesToUser(               db.setSecondaryOk(
db.dropRole(                       db.groupeval(                      db.setSlaveOk(
db.dropUser(                       db.hasOwnProperty                  db.setWriteConcern(
db.enableFreeMonitoring(           db.hello(                          db.shutdownServer(
db.eval(                           db.help(                           db.stats(
db.forceError(                     db.hoge                            db.system.users
db.fsyncLock(                      db.hostInfo(                       db.system.version
db.fsyncUnlock(                    db.isMaster(                       db.toLocaleString
db.getCollection(                  db.killOP(                         db.toString(
db.getCollectionInfos(             db.killOp(                         db.tojson(
db.getCollectionNames(             db.listCommands(                   db.unsetWriteConcern(
db.getFreeMonitoringStatus(        db.loadServerScripts(              db.updateRole(
db.getLastError(                   db.logout(                         db.updateUser(
db.getLastErrorCmd(                db.printCollectionStats(           db.valueOf(
db.getLastErrorObj(                db.printReplicationInfo(           db.version(
db.getLogComponents(               db.printSecondaryReplicationInfo(  db.watch(
> db.

MongoDBを使ってなにか開発をしてみたいなと思いましたね。

ただ、RDBと違ってかなり自由なので考え方とかが違う点が多々あるので最初は戸惑いそうです。

参考記事

【Windows】RDBMS歴が長い人でも大丈夫!MongoDB超入門 | CodeCampus

MongoDB超入門 - Qiita

Documents — MongoDB Manual

MongoDBを始めた頃に知っていたら、と思う14のこと

MongoDBコマンド一覧(自分用メモ) - Qiita

やってみようNoSQL MongoDBを最速で理解する - Qiita