Mongoコマンドとか初心者が苦しんだ所を書き残す。


初めに

初投稿です!
MongoDBを初めて触る機会があり、いろいろと詰まったことを忘れないために書き残します。

まだ初心者エンジニアなので、勘違い等あるかと思いますが、間違い等ありましたら、指摘していただけると勉強になります!
書いてることは基本的にはMongoDB公式Documentに載っているはずです。

コマンド

GET-find

シンプルな検索
db.コレクション名.find({key: value})の形で検索をする。find()とすると全件を取得する。

[sample]
db.Collection.find({key1:fuga})

And条件での検索
db.Collection.find({ key1:fuga, key2:hoge })
db.inventory.find( { $and: [ { key1:  10  }, { key2: 20 } ] } )

Or条件での検索
db.Collection.find({key1: [ fuga, hoge ] })
db.inventory.find( { $or: [ { key1:  10  }, { key2: 20 } ] } )

ソート
sort({Key名:1(ASC) or -1(DESC)})で表現される。複数条件も可。
db.Collection.find().sort({key1:1})

カウント
数値を入れるだけ。
db.Collection.find().limit(10)

オフセット
数値を入れるだけ。
db.Collectuon.find().skip(10)

INSERT-insert

Mongo
mongo特有のPrimaryKeyのようなものとして、_id(ObjectId)が自動で付与される。
また、Bsonの形式で保存される(このまま文字列として保存されるようなもの)ので、変数名を短くすると少し軽くなることもある(らしい)。

また、今回はInsertですが、InsertOneやInsertManyのコマンドも知っていると便利でした!

db.Collection.insert({'key1':'value'})

UPDATE-update

db.Collection.update({条件式},{セット内容})
db.Collection.update({key1:fuga},{$set: {key2:hogehoge}})

DELETE-delete

db.Collection.delete({条件式})
db.Collection.delete({key1:fuga})

AGGREGATEについて

Aggregateは集計用の関数です。
PipeLineとよばれる段階的な処理をする構造で、その処理の段階の単位をステージと表現されます。

※イメージ(配列の形であらわされており、1要素あたり1ステージ)

PipeLine[ Stage1, Stage2, Stage3]

複雑な検索、集計処理を行う場合、Aggregateを用いることになると思います。

このAggregateが使いこなせると、Mongoって便利やなぁ…ってなります。
Aggregateを使うとJoinっぽいことができます。Joinを通してAggregateの使い方を書き残します。

Joinがしたい

lookup

Aggregateのパイプラインステージの$lookupを使うと、MongoでJoinっぽいことができます。

簡単に言うと、ジョイン先のコレクションに対して、検索をして、その結果をasに書いた名前の配列としてジョイン元ドキュメントに追加します。

また、lookupにはジョイン先、すなわち検索先コレクションに対してPipeLineを使うことができます。その場合、少し書き方が違うため、双方のパターンの実装例を示しておきます。(PipeLineを使わない実装はPipeLineを使う実装を簡略化したものだと思われます。)

実装例

PipeLineを使わない(Join先に検索をしない)

db.Collection.aggregate([{$lookup:
                            from: <ジョイン先のコレクション名>,
                            localField: <ジョイン元の紐づけるためのField>,
                            foreignField: <ジョイン先の紐づけるためのField>,
                            as: <ジョイン情報の名前>
                        }])

PipeLineを使う(Join先に検索をする)

db.Collection.aggregate([
                        {
                            $lookup:{
                            from: <ジョイン先のコレクション名>,
                            localField: <ジョイン元の紐づけるためのField>,
                            foreignField: <ジョイン先の紐づけるためのField>,
                            as: <ジョイン情報の名前>
                            }
                        },
                        {
                            $unwind: $ + <ジョイン情報の名前>
                        }
                        ])

unwind

上記のlookupで取得した結果は配列になっています。配列に対する検索をする場合、$unwindを使って、配列を展開する必要があります。

展開するイメージとしては、下記のようになります。

unwindイメージ

{
    _id: 123,
    name: "伝説太郎",
    hobby: ["釣り", "買い物", "キャンプ"]
}

↓↓↓

{
    _id: 123,
    name: "山田太郎",
    hobby: "釣り"
},
{
    _id: 123,
    name: "山田太郎",
    hobby: "買い物"
},
{
    _id: 123,
    name: "山田太郎",
    hobby: "キャンプ"
},

実装例

※Mongo公式様のサンプルから引用です。

db.Collection.aggregate([
                        {
                            $lookup:{
                            from: <ジョイン先のコレクション名>,
                            localField: <ジョイン元の紐づけるためのField>,
                            foreignField: <ジョイン先の紐づけるためのField>,
                            as: <ジョイン情報の名前>
                            }
                        },
                        {
                            $unwind: $ + <ジョイン情報の名前>
                        }
                        ])

db.Collection.aggregate([
                            {
                            $lookup:
                                {
                                from: <ジョイン先のコレクション名>, 
                                // letはPipeLineで使用する変数を指定します
                                let: { order_item: "$item", order_qty: "$ordered" },
                                pipeline: [
                                    { $match:
                                        { $expr:
                                            { $and:
                                            [
                                                { $eq: [ "$stock_item",  "$$order_item" ] },
                                                { $gte: [ "$instock", "$$order_qty" ] }
                                            ]
                                            }
                                        }
                                    },
                                    { $project: { stock_item: 0, _id: 0 } }
                                ],
                                as: <ジョイン情報の名前>
                                }
                            }
                        ])

match

ようやく検索です。findの時の書き方とそこまで変わりはありません。

$exprについては↓にちょっとだけ書きました。

{ $match:
           { $expr:
                   { $and:
                   [
                       { $eq: [ "$stock_item",  "$$order_item" ] },
                       { $gte: [ "$instock", "$$order_qty" ] }
                   ]
                   }
           }
}

比較演算子

同一ドキュメント内の変数を比較する場合

\$exprを用いる。パイプラインステージのlookupの時の$letに近いもの。

実装例

$expr: {
          $and: [
            { $eq: ["$hobby", "$name"] },
            { $gt: ["$age", "$date"] }]
        }

おわりに

自分用の忘備録なので読みづらい文章で申し訳ないです。
私と同じ初心者さんで、わからないところや詰まってること等ありましたら、気軽にコメントしてください。
私にわかる範囲でならお答えします!

参考にさせていただいたページ様方

MongoDB コマンドメモとか書き
MongoDB で コレクションを結合する 方法
MongoDBのAggregationでRDBみたいな使い方