Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

RDB脳でもMongoDBを使い倒したい!

RDBリレーショナル・データベース強すぎでは???」と思っていました。MongoDBに出会うまでは

MongoDBはJSONベースでやりとりができるので、かなりJSerにやさしくて涙が出ちゃいました(出てない)。

しかし、RDBをかじっていたせいで脳が凝り固まっており、「どうやって設計すれば良いんだ??」と途方にくれていました。しかし、そこでMongoDBにおける関連(Relation)のスキーマ設計という記事を見つけてしまい、神の意思を感じました。

先に言っておきますが、「製品版のときはRDBでキッチリと管理したい」「けどまだスキーマが固まってないプロトタイプの段階ではMongoDBでゴリゴリしたい」人なのでRDB派とも共存していきたいです。

RDB脳がMongoDBをあつかう

詳しくは先程ご紹介した記事を読んでいただきたいです。ここではザックリとまとめます

  • One-to-Manyのときは基本的に「埋め込む」ことでリレーションをなくす
  • たとえば「ある人のツイート」は「その人のアカウントに直接ぶらさげる」形にする
  • ただし件数が多くなるとこれは逆にパフォーマンスが悪いので素直に分離する
  • 分離した場合はアプリケーション側で結合する
  • Many-to-Manyも中間テーブルなしで直接IDを埋め込んで対応できる

要するに「RDBより直感に沿った実装にできる」感じです(個人の感想)。JSONで出来てしかも実装がわかりやすいなんて、神すぎますね。

実装するためのTips

上の記事には実装のTipsがありませんでした。そこで、調べてまとめてみました。

各コードは以下のコードをベースとしています。また、以下のコードはPHP7で新しいMongoDBのドライバを使う参考にパクりました(自白)。MongoDBのインストールなどについても書いてあるので、リンク先はぜひご覧ください。

<?php
require_once __DIR__ . '/vendor/autoload.php';

$client = new MongoDB\Client("mongodb://localhost:27017");
$db = $client->selectDatabase('example');
$collection = $db->selectCollection('shop');

$collection->drop();
$collection->insertMany([
    [ 'shop' => '甘兎庵', 'members' => [ ['name' => '宇治松千夜', 'cv' => '佐藤聡美' ] ] ],
    [ 'shop' => 'フルール・ド・ラパン', 'members' => [ [ 'name' => '桐間紗路', 'cv' => '内田真礼'] ] ],
    [ 'shop' => 'ラビットハウス', 'members' => [
        [ 'name' => '保登心愛', 'cv' => '佐倉綾音' ],
        [ 'name' => '香風智乃', 'cv' => '水瀬いのり' ],
        [ 'name' => '天々座理世', 'cv' => '種田梨沙' ],]
    ]
]);

要素を追加(Create)

「ツイートする」ように、埋め込んであるデータに要素を追加します

<?php
$collection->updateOne(['shop' => 'ラビットハウス'], ['$push' => ['members' => [ 'name' => '条河麻耶', 'cv' => '徳井青空' ]]]);

ラビットハウスにマヤちゃんがバイトに来た回のことです。

要素を削除(Delete)

<?php
$collection->updateOne(['shop' => 'ラビットハウス'], ['$pull' => ['members' => [ 'name' => '保登心愛' ]]]);

ココアが帰省したときの話です。

要素を更新(Update)

<?php
$collection->updateOne(['shop' => 'ラビットハウス'], ['$set' => ['members.0.name' => 'ココアお姉ちゃん' ]]);

心愛をココアお姉ちゃんと変更します。

また、ココアが配列でどこにいるのか知らずとも、以下のように更新することもできます。

<?php
$collection->updateOne(['shop' =>  '甘兎庵', 'members.name' =>  '宇治松千夜'], ['$set' => ['members.$.name' => 'チヤお姉ちゃん']]);

このコードは『「宇治松千夜」という名前の店員の名前を「チヤお姉ちゃん」とする』という動作をします。先程の例ではココアの位置を知っていなければなりませんでしたが、これではチヤお姉ちゃんが配列でどこにいるのか知らずとも変更ができます。

まとめ

ごちうさ3期おめでとう(激遅)