やりたいこと
mongo 互換の AWS DocumentDB に mongoose から接続したい。
mongoose で docker でたてた MongoDB に接続するのにはまった話
以前書いたような感じで接続したい。
今回の環境は、AWS で立てた AmazonLinux2 インスタンスからの接続。
$ cat /etc/os-release
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"
$ node -v
v14.8.0
なお、DocumentDB は、Tokyo Region でも使える。ちと高い気もするが、EC2 インスタンス上に MongoDB をインストールして、バックアップだなんだと諸々の手間を考えると、個人では遠慮したいところだが、会社ならまぁ良いのでは?という感じ。
DocumentDB のクラスターを立ち上げるためには、インスタンスを1つしか立ち上げないとしても、VPC は Multi AZ 構成になっている必要がある。
DocumentDB の接続方法
特に何も考えずに普通に DocumentDB を立ち上げると、インスタンス情報の Connectivity & Security という項目に、
まずは、pem をダウンロードし、それを使って接続しろと書いてある。
曰く、
Download the Amazon DocumentDB Certificate Authority (CA) certificate required to authenticate to your instance
wget https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pemmongo シェルでこのインスタンスに接続する
mongo --ssl --host xxxx.xxxx.ap-northeast-1.docdb.amazonaws.com:27017 --sslCAFile rds-combined-ca-bundle.pem --username xxxx --password <insertYourPassword>アプリケーションでこのインスタンスに接続する
mongodb://xxxx:<insertYourPassword>@xxxx.xxxx.ap-northeast-1.docdb.amazonaws.com:27017/?ssl=true&ssl_ca_certs=rds-combined-ca-bundle.pem&retryWrites=false
こんな感じ。
Node アプリから mongoose で接続
Shell を用いての接続はうまくいくけど、node アプリからの接続は、どうしたら良いの?と探してみたところ、stackoverflow に答えがあった。
connection error while connecting to AWS DocumentDB
で、結局こうなった。
constmongoose=require('mongoose');constfs=require('fs');mongoose.connect('mongodb://xxxx.xxxx.ap-northeast-1.docdb.amazonaws.com:27017',{useNewUrlParser:true,useUnifiedTopology:true,ssl:true,sslValidate:false,sslCA:fs.readFileSync('./rds-combined-ca-bundle.pem'),user:'<userName>',pass:'<password>',dbName:'<dbName>'});constCat=mongoose.model('Cat',{name:String});constkitty=newCat({name:'Zildjian'});kitty.save().then(()=>console.log('meow'));
pem ファイルは、fs で読み込まないと、monngoose 側でうまくやってくれたりはしない。
実行してみる。
$ node index.js
meow
いったっぽい。
Shell から入って確認。
rs0:PRIMARY> show collections
cats
rs0:PRIMARY> db.cats.find()
{ "_id" : ObjectId("5f478c677f7fde2e..."), "name" : "Zildjian", "__v" : 0 }
成功。
余談
MongoDB は、ほぼほぼ JSON な扱いが出来たりなど、アプリ開発者としては、非常に使いやすいが、MySQL などのようにお手軽にインフラ構築が出来ない。し、ちょっと高い。コンテナなどを使えば良いんだろうけど、運用する場合、ただ立ち上がれば良いという話ではないし。
なので、本当に MongoDB でなきゃダメか?は、インフラ担当者と話し合って決めるのが幸せだと思う。