MongoDB (例題)

# 目次
- create, drop collection
- find
- strLenCP
- distinct
- count
- index
- and
- in, not, nin, regex
- gt, gte, lt, lte
- skip, limit
- unwind
- project
- addFields
- dateToString
- concatArrays, concat
- exists
- cond, if
- switch
- where
- 更新
- グループ、カウント、SUM、MAX
- 同じDB内のCollectionの結合
- 異なるDBのCollectionの更新コマンド]
- 小さい処理
- function
- dump/restore, export/import


## 当例題は、下記データを元に記載したクエリと実行結果になります。

## DB Name : Employee, Collection Name : emp
|_id|emp_id|emp_name|emp_class|hobby|salary|delete_flg|reflect_flg|create_date|update_date|
|---|---|---|---|---|---|---|---|---|---|
|ObjectId(....1)|1001|Emp1|100|["reading", "music"]|1000|0||2021-01-01|ISODate("2021-01-15T02:50:00.304Z")|
|ObjectId(....2)|1002|Emp2|100|["writing", "music"]|2000|0||2021-02-01|ISODate("2021-01-15T02:50:00.304Z")|
|ObjectId(....3)|1003|Emp3|100|["speaking", "music"]|3000|0||2021-03-01|ISODate("2021-01-15T02:50:00.304Z")|
|ObjectId(....4)|1004|Emp4|200|["teaching", "music"]|4000|0||2021-04-01|ISODate("2021-01-15T02:50:00.304Z")|
|ObjectId(....5)|1005|Emp5|200|["learning", "music"]|5000|0|null|2021-05-01|ISODate("2021-01-15T02:50:00.304Z")|
|ObjectId(....6)|1006|Emp6|300|["reading", "music"]|6000|0|0|2021-06-01|ISODate("2021-01-15T02:50:00.304Z")|
|ObjectId(....6)|1007|Emp7|300|["reading"]||1|0|2021-07-01|ISODate("2021-01-15T02:50:00.304Z")|
|ObjectId(....6)|1008|Emp8|300|["music"]|8000|0|1|2021-08-01|ISODate("2021-01-15T02:50:00.304Z")|

# create, drop collection

```
# Employee DBのempコレックションを作成する
db.getSiblingDB("Employee").createCollection("emp")

# Employee DBのempコレックションを削除する
db.getSiblingDB("Employee").getCollection("emp").drop()
```

# find

```
# empの全てのドキュメントを抽出する
db.getCollection("emp").find({})

# 全てのempドキュメントのemp_id列のみ抽出する（_idは指定しないとデフォルトで表示される）
# 1：表示、0：非表示
db.getCollection("emp").find({}, {"_id" : 0, "emp_id" : 1})

# emp_id昇順で抽出する
# 1：昇順、-1：降順
db.getCollection(“emp”)
.find({})
.sort({"emp_id" : 1})
.collation({ locale: "jp", numericOrdering: true })
※collation指定は、文字ソートする場合に必要
（ない場合「1, 11, 2, 3」順になる、あう場合「1, 2, 3, 11」順になる）
```

#### 「null, 値有無」のreflect_flg列の操作結果

```
# １. 全てのdocumentの抽出
> db.getCollection('emp').find({}, {"_id" : 0, "emp_id" : 1, "reflect_flg" : 1})
{ "emp_id" : "1001" }
{ "emp_id" : "1002" }
{ "emp_id" : "1003" }
{ "emp_id" : "1004" }
{ "emp_id" : "1005", "reflect_flg" : null }
{ "emp_id" : "1006", "reflect_flg" : "0" }
{ "emp_id" : "1007", "reflect_flg" : "0" }
{ "emp_id" : "1008", "reflect_flg" : "1" }
```

```
# ２. reflect_flg存在しない、かつ、null設定のdocumentの抽出
> db.getCollection('emp').find({"reflect_flg" : null}, {"_id" : 0, "emp_id" : 1, "reflect_flg" : 1})
{ "emp_id" : "1001" }
{ "emp_id" : "1002" }
{ "emp_id" : "1003" }
{ "emp_id" : "1004" }
{ "emp_id" : "1005", "reflect_flg" : null }
```

```
# ３. reflect_flgの存在しないのdocumentの抽出
> db.getCollection('emp').find({"reflect_flg" : {$exists : false}}, {"_id" : 0, "emp_id" : 1, "reflect_flg" : 1})
{ "emp_id" : "1001" }
{ "emp_id" : "1002" }
{ "emp_id" : "1003" }
{ "emp_id" : "1004" }
```


```
# ４. reflect_flgが存在し、null設定のdocumentの抽出
> db.getCollection('emp').find({"reflect_flg" : {$exists : true, $eq : null} }, {"_id" : 0, "emp_id" : 1, "reflect_flg" : 1}) // will be 'and' condition
{ "emp_id" : "1005", "reflect_flg" : null }
```

```
# ５. reflect_flgが存在し、null設定ではないdocumentの抽出
> db.getCollection('emp').find({"reflect_flg" : {$ne : null}}, {"_id" : 0, "emp_id" : 1, "reflect_flg" : 1})
> db.getCollection('emp').find({"reflect_flg" : {$exists : true, $ne : null}}, {"_id" : 0, "emp_id" : 1, "reflect_flg" : 1})

{ "emp_id" : "1006", "reflect_flg" : "0" }
{ "emp_id" : "1007", "reflect_flg" : "0" }
{ "emp_id" : "1008", "reflect_flg" : "1" }
```

```
# ６. reflect_flgが存在するdocumentの抽出
> db.getCollection('emp').find({"reflect_flg" : {$exists : true}}, {"_id" : 0, "emp_id" : 1, "reflect_flg" : 1})
> db.getCollection('emp').find({"reflect_flg" : null, "reflect_flg" : {$exists : true} }, {"_id" : 0, "emp_id" : 1, "reflect_flg" : 1}) // will be 'or' condition

{ "emp_id" : "1005", "reflect_flg" : null }
{ "emp_id" : "1006", "reflect_flg" : "0" }
{ "emp_id" : "1007", "reflect_flg" : "0" }
{ "emp_id" : "1008", "reflect_flg" : "1" }
```

# strLenCP

```
# 社員名の文字数が4桁の社員を抽出する
db.getCollection('emp').find({ "$expr": { "$eq": [ { "$strLenCP": "$emp_name" }, 4 ] } },
 { "_id" : 0, "emp_id" : 1, "emp_name" : 1 }) 

＞結果
{ "emp_id" : "1001", "emp_name" : "Emp1"}
{ "emp_id" : "1002", "emp_name" : "Emp2"}
{ "emp_id" : "1003", "emp_name" : "Emp3"}
{ "emp_id" : "1004", "emp_name" : "Emp4"}
{ "emp_id" : "1005", "emp_name" : "Emp5"}
{ "emp_id" : "1006", "emp_name" : "Emp6"}
{ "emp_id" : "1007", "emp_name" : "Emp7"}
{ "emp_id" : "1008", "emp_name" : "Emp8"}
```

# distinct

```
# 重複なしのemp_classを抽出する
db.getCollection("emp").distinct("emp_class")

＞結果
[
  “100”,
  “200”,
  “300”
]
```


```
# 条件付：削除フラグ＝0 中の重複なしのreflect_flgを抽出する
db.getCollection('emp').distinct("reflect_flg", {"delete_flg" : "0"})

＞結果
[
    null,
    "0",
    "1"
]
```


```
# 重複なしのreflect_flgのサイズを取得する
db.getCollection('emp').distinct("reflect_flg", {"delete_flg" : "0"}).length

＞結果
3
```

# count

```
# emp Collectionの件数を抽出する
Db.getCollection(“emp”).find({}).count()
```

＞結果

```
8
```

# index

```
# emp Collectionのemp_idに対して、インデックスを設定する
db..getCollection("emp").createIndex({ emp_id: 1}, { name : "pk_key" })
```

```
# 「unique : true」がある場合、「emp_idとemp_name」の重複データが登録出来ないようになる
db..getCollection("emp").createIndex({ emp_id: 1, emp_name: 1 }, { name : "pk_key", unique : true })
```

```
# インデックスを設定する
db.getCollection("emp").createIndex({ emp_name: 1}, { name : "empName_index" })
# インデックスを削除する
db.getCollection("emp").dropIndex("empName_index")
```

# and

```
# 趣味が読書一個のみのempを検索し、emp_id, hobby列のみ表示する
db.getCollection(“emp”).find({
  $and : [
    { "hobby" : "reading" },
    { "hobby" : { $size : 1 } }
  ] 
}, { "_id" : 0, "emp_id" : 1, "hobby" : 1 })
```

＞結果

```
{ "emp_id" : "1007", "hobby" : [ "reading" ] }
```

# in, not, nin, regex

```
# $in：趣味が読書、書くのempを抽出する
db.getCollection(“emp”).find(
 { "hobby" : { $in : ["reading", "writing"] } },
 { "_id" : 0, "emp_id" : 1, "hobby" : 1 } )

# 結果
{ "emp_id" : "1001", "hobby" : [ "reading", "music" ] }
{ "emp_id" : "1002", "hobby" : [ "writing", "music" ] }
{ "emp_id" : "1006", "hobby" : [ "reading", "music" ] }
{ "emp_id" : "1007", "hobby" : [ "reading" ] }
```

```
# $not, $in：趣味が聞く以外のempを抽出する
db.getCollection(“emp”).find(
 { "hobby" : { $not : { $in : ["music"] } } },
 { "_id" : 0, "emp_id" : 1, "hobby" : 1 })

または

db.getCollection(“emp”).find(
 { "hobby" : { $nin : ["music"] } },
 { "_id" : 0, "emp_id" : 1, "hobby" : 1 })

# 結果
{ "emp_id" : "1007", "hobby" : [ "reading" ] }
```

```
# $regex：趣味がmu開始文字以外のempを抽出する
db.getCollection(“emp”).find(
 { "hobby" : { $not : { $regex : /^mu/ } } },
 { "_id" : 0, "emp_id" : 1, "hobby" : 1} )

または

db.getCollection(“emp”).find(
 { "hobby" : { $not : { $in : /^mu/ } } },
 { "_id" : 0, "emp_id" : 1, "hobby" : 1} )


# 結果
{ "emp_id" : "1007", "hobby" : [ "reading" ] }
```

# gt, gte, lt, lte

```
# 更新日が2021-02-01以降のempを件数を出す
# 結果：0件
db.getCollection(“emp”).find(
{ "update_date" : { $gte : ISODate("2021-02-01") } }
).count()

# 2021-01-01 < 更新日 <= 2021-02-01のempを件数を出す
# 結果：8件
db.getCollection(“emp”).find(
{ "update_date" : { $gt : ISODate("2021-01-01"),
                    $lte : ISODate("2021-02-01") } 
}
).count()

# 更新日< 2021-02-01、かつ、登録日が2021-01-01のempを件数を出す
# 結果：1件
db.getCollection(“emp”).find(
{ "update_date" : { $lt : ISODate("2021-02-01") },
  "create_date" : "2021-01-01" 
}
).count()
```

# skip, limit

```
# skip, limit指定前の結果
# 趣味が読書と書くのempを抽出する
db.getCollection(“emp”).find(
 { "hobby" : { $in : ["reading", "writing"] } },
 { "_id" : 0, "emp_id" : 1, "hobby" : 1 } )
.sort({"emp_id" : 1})

# 結果
{ "emp_id" : "1001", "hobby" : [ "reading", "music" ] }
{ "emp_id" : "1002", "hobby" : [ "writing", "music" ] }
{ "emp_id" : "1006", "hobby" : [ "reading", "music" ] }
{ "emp_id" : "1007", "hobby" : [ "reading" ] }
```

```
# skip, limit指定後の結果
# 趣味が読書と書くのempの中、３番目から１ドキュメントを抽出する
db.getCollection(“emp”).find(
 { "hobby" : { $in : ["reading", "writing"] } },
 { "_id" : 0, "emp_id" : 1, "hobby" : 1 } )
.sort({"emp_id" : 1})
.skip(2)
.limit(1)

# 結果
{ "emp_id" : "1006", "hobby" : [ "reading", "music" ] }

または

db.getCollection(“emp”).find(
 { "hobby" : { $in : ["reading", "writing"] } },
 { "emp_id" : 1, $skip : 2, $limit : 1 } )
# 結果
{ "_id" : ObjectId(....6), "emp_id" : "1006" }
```


# unwind 

```
# emp_id=1001のdocumentを抽出する
db.getCollection('emp').find({"emp_id" : "1001"}, { "_id" : 0, "emp_id" : 1, "hobby" : 1})

# 結果
{ "emp_id" : "1001", "hobby" : ["reading", "music"] }
```

```
# emp_id=1001のhobby配列の値ごとにdocumentを抽出する
db.getCollection('emp').aggregate( [ 
  { $match : {"emp_id" : "1001"} },
  { $unwind : "$hobby" },
  { $project : { "_id" : 0, "emp_id" : 1, "hobby" : 1} }
] )

# 結果
{ "emp_id" : "1001", "hobby" : "reading"}
{ "emp_id" : "1001", "hobby" : "music"}
```

#### 配列中身のデータに該当するデータを出す

##### arrayObjectTestコレクションに社員に対する質問と回答のデータが存在する
```
/* 1 */
{
    "_id" : ObjectId("6226c0ee4c62c33e842e4bb0"),
    "questionId" : "1",
    "emp_id" : "1001",
    "questionList" : [ 
        {
            "qId" : "1",
            "questionName" : "好きな食べ物",
            "answerList" : [ 
                {
                    "answerId" : "1",
                    "answerText" : "肉"
                }, 
                {
                    "answerId" : "2",
                    "answerText" : "ケーキ"
                }, 
                {
                    "answerId" : "3",
                    "answerText" : "野菜"
                }
            ],
            "resultText" : ""
        }, 
        {
            "qId" : "2",
            "questionName" : "好きな音楽",
            "answerList" : [ 
                {
                    "answerId" : "1",
                    "answerText" : "POP"
                }, 
                {
                    "answerId" : "2",
                    "answerText" : "R&B"
                }
            ],
            "resultText" : ""
        }
    ],
    "createDate" : ISODate("2022-01-01T01:09:44.542Z")
}
/* 2 */
{
    "_id" : ObjectId("6226c1144c62c33e842e4beb"),
    "questionId" : "2",
    "emp_id" : "1002",
    "questionList" : [ 
        {
            "qId" : "1",
            "questionName" : "好きな食べ物",
            "answerList" : [ 
                {
                    "answerId" : "1",
                    "answerText" : "ケーキ"
                }, 
                {
                    "answerId" : "2",
                    "answerText" : "野菜"
                }
            ],
            "resultText" : ""
        }, 
        {
            "qId" : "2",
            "questionName" : "好きな音楽",
            "answerList" : [ 
                {
                    "answerId" : "1",
                    "answerText" : "POP"
                }
            ],
            "resultText" : ""
        }
    ],
    "createDate" : ISODate("2022-02-01T01:09:44.542Z")
}
```

```
# 答えに「ケーキ」がある質問に該当する、questionId, answerIdとanswerTextを出す
db.getCollection('arrayObjectTest').aggregate([
 { "$unwind": "$questionList" }
 , { "$unwind": "$questionList.answerList" }
 , { "$match": { "questionList.answerList.answerText" : "ケーキ" } }
 , { "$addFields": { "answerId": { $concat : ["", "$questionList.answerList.answerId"] },
                     "answerText": { $concat : ["", "$questionList.answerList.answerText"] } } }
 , { "$project" : {"_id":0, "questionId" : 1, "answerId"  : 1, "answerText"  : 1} }
])

## 結果
{ "questionId" : "1", "answerId" : "2", "answerText" : "ケーキ"}
{ "questionId" : "2", "answerId" : "1", "answerText" : "ケーキ"}
```

# project

```
# insert document
db.getCollection('order_info').insert(
{
    "item_id" : NumberLong(1),
    "stock_info" : ["cloth", "winter"],
    "order_info" : ["men", "kids"]
})

> db.getCollection('order_info').find({})
{
 "_id" : ObjectId("61b1d6ea29182be1a230d25d"),
 "item_id" : NumberLong(1), 
 "stock_info" : ["cloth", "winter"], 
 "order_info" : ["men", "kids"]
}
```

```
# item_id項目のみ、出力する
db.getCollection('order_info').aggregate( [ 
  { $project: { "_id" : 0,  "item_id" : 1} }
] )

# 結果
{ "item_id" : 1 }
```


# addFields

```
# insert document
db.getCollection('order_info').insert(
{
    "item_id" : NumberLong(1),
    "stock_info" : ["cloth", "winter"],
    "order_info" : ["men", "kids"]
})

> db.getCollection('order_info').find({})
{
 "_id" : ObjectId("61b1d6ea29182be1a230d25d"),
 "item_id" : NumberLong(1), 
 "stock_info" : ["cloth", "winter"], 
 "order_info" : ["men", "kids"]
}
```

```
# item_id項目のみ、出力する
db.getCollection('order_info').aggregate( [ 
  { $addFields: { "new_column": "Test" } }
] )

# 結果
{
    "_id" : ObjectId("61b1d6ea29182be1a230d25d"),
    "item_id" : NumberLong(1), 
    "stock_info" : ["cloth", "winter"], 
    "order_info" : ["men", "kids"],
    "new_column" : "Test"
}
```

# dateToString

```
db.getCollection('emp').aggregate(
[ {"$addFields": { update_date2: { $dateToString : { format: "%Y年%m月%d日 %H:%M:%S.%L", date: "$update_date" } } } },
  {"$project" : { "_id" : 0, "emp_id" : 1, "update_date" : 1, "update_date2" : 1 } }
])

＞結果
{"emp_id" : "1001", "update_date" : ISODate("2021-01-15T02:50:00.304Z"), "update_date2" : "2021年01月15日 02:50:00.304"}
{"emp_id" : "1002", "update_date" : ISODate("2021-01-15T02:50:00.304Z"), "update_date2" : "2021年01月15日 02:50:00.304"}
{"emp_id" : "1003", "update_date" : ISODate("2021-01-15T02:50:00.304Z"), "update_date2" : "2021年01月15日 02:50:00.304"}
{"emp_id" : "1004", "update_date" : ISODate("2021-01-15T02:50:00.304Z"), "update_date2" : "2021年01月15日 02:50:00.304"}
{"emp_id" : "1005", "update_date" : ISODate("2021-01-15T02:50:00.304Z"), "update_date2" : "2021年01月15日 02:50:00.304"}
{"emp_id" : "1006", "update_date" : ISODate("2021-01-15T02:50:00.304Z"), "update_date2" : "2021年01月15日 02:50:00.304"}
{"emp_id" : "1007", "update_date" : ISODate("2021-01-15T02:50:00.304Z"), "update_date2" : "2021年01月15日 02:50:00.304"}
{"emp_id" : "1008", "update_date" : ISODate("2021-01-15T02:50:00.304Z"), "update_date2" : "2021年01月15日 02:50:00.304"}
```

# concatArrays, concat

```
# insert document
db.getCollection('order_info').insertMany([
{
    "item_id" : NumberLong(1),
    "stock_info" : ["cloth", "winter"],
    "order_info" : ["men", "kids"]
},
{
    "item_id" : NumberLong(2),
    "item_name" : "spring",
    "item_type" : "cloth",
    "stock_info" : ["cloth", "spring"],
    "order_info" : ["men", "kids"]
}])
```

```
# 配列(stock_info, order_info)の値を繋ぐする、かつ、item_nameとitem_typeの文字列を繋ぐ
db.getCollection('order_info').aggregate( [
  { $project: { "_id" : 0,
                "concatArrays" : { $concatArrays: [ "$stock_info", "$order_info" ] },
                "concat" : { $concat: [ "$item_name", " - ", "$item_type" ] }
    } 
  }
] )

# 結果
{ "concatArrays" : [ cloth", "winter", "men", "kids"], "concat" : null }
{ "concatArrays" : [ cloth", "spring", "men", "kids"], "concat" : "concat" : "spring- cloth" }
```

# exists

```
# reflect_flg列が存在し、「1」に該当するempを抽出する
db.getCollection('emp').find({"reflect_flg" : {$exists : true, $eq : "1"}} // can also add for type (eg. name : { $exists: true, $not: { $type: "array" }, $type: "object" })
, {"_id" : 0, "emp_id" : 1, "reflect_flg" : 1 })

> 結果
{
    "emp_id" : "1008",
    "reflect_flg" : "1"
}
```

# cond, if

```
# emp_class=100の場合は「100 class」を出力する。それ以外は「Other class」をを出力する。
db.getCollection('emp').aggregate([
  { "$addFields": { "condition_result" : 
                         {$cond: {if: { $eq: [ "$emp_class", "100" ] }, 
                                    then: "100 class",
                                  else: 
                                    "Other class" }}}
  },
  {"$project" : {"_id" : 0, "emp_id": 1, "emp_class" : 1, "condition_result" : 1}}
])

または

db.getCollection('emp').aggregate([
  { "$addFields": { "condition_result" : 
                         {$cond: [ { $eq: [ "$emp_class", "100" ] },
                                   "100 class",
                                   "Other class" 
                                 ]}}
  },
  {"$project" : {"_id" : 0, "emp_id": 1, "emp_class" : 1, "condition_result" : 1}}
])

または

db.getCollection('emp').aggregate([
  {"$project" : {"_id" : 0, "emp_id": 1, "emp_class" : 1,
                 "condition_result" : {$cond: [ { $eq: [ "$emp_class", "100" ] },
                                               "100 class",
                                               "Other class" 
                                       ]}
              }
   }
])
```

```
＞結果
{ "emp_id" : "1001", "emp_class" : "100", "condition_result" : "100 class" }
{ "emp_id" : "1002", "emp_class" : "100", "condition_result" : "100 class" }
{ "emp_id" : "1003", "emp_class" : "100", "condition_result" : "100 class" }
{ "emp_id" : "1004", "emp_class" : "200", "condition_result" : "Other class" }
{ "emp_id" : "1005", "emp_class" : "200", "condition_result" : "Other class" }
{ "emp_id" : "1006", "emp_class" : "300", "condition_result" : "Other class" }
{ "emp_id" : "1007", "emp_class" : "300", "condition_result" : "Other class" }
{ "emp_id" : "1008", "emp_class" : "300", "condition_result" : "Other class" }
```

# switch

```
# insert data
db.getCollection('grade_info').insertMany([
{ "name" : "Susan Wilkes", "scores" : [ 87, 86, 78 ] },
{ "name" : "Bob Hanna", "scores" : [ 71, 64, 81 ] },
{ "name" : "James Torrelio", "scores" : [ 91, 84, 97 ] }
])
```

```
# scoresの平均(x)の下記を出力する
#  ・x <= 40は、low scroes
#  ・40 < x <= 80は、medium scroes
#  ・その他は、hight scroes
db.getCollection('grade_info').aggregate([
  {"$project" : {"_id" : 0, "name": 1, "scores" : 1,
                 "average_salary" : {$avg : "$scores"},
                 "condition_result" : {
                    $switch: {
                       branches: [
                         { case: { $lte : [ { $avg : "$scores" }, 40 ] }, then: "low scores" },
                         { case: { $and : [ { $gt : [ { $avg : "$scores" }, 40 ] },
                                            { $lte  : [ { $avg : "$scores" }, 80 ] } ] }, then: "medium scores" }
                                           ],
                         default: "hight scores"
                      }
                 }
   }}
])

＞結果
{ "name" : "Susan Wilkes", "scores" : [ 87, 86, 78 ], "average_salary" : 83.6666666666667, "condition_result" : "hight scores" },
{ "name" : "Bob Hanna", "scores" : [ 71, 64, 81 ], "average_salary" : 72.0, "condition_result" : "medium scores" },
{ "name" : "James Torrelio", "scores" : [ 91, 84, 97 ], "average_salary" : 90.6666666666667, "condition_result" : "hight scores" }
```

# where 

```
# データ確認
> db.getCollection('emp').find({}, {"_id" : 0, "emp_id" : 1, "hobby" : 1})
{ "emp_id" : "1001", "hobby" : [ "reading", "music" ] }
{ "emp_id" : "1002", "hobby" : [ "writing", "music" ] }
{ "emp_id" : "1003", "hobby" : [ "speaking", "music" ] }
{ "emp_id" : "1004", "hobby" : [ "teaching", "music" ] }
{ "emp_id" : "1005", "hobby" : [ "learning", "music" ] }
{ "emp_id" : "1006", "hobby" : [ "reading", "music" ] }
{ "emp_id" : "1007", "hobby" : [ "reading" ] }
{ "emp_id" : "1008", "hobby" : [ "music" ] }
```

```
# 趣味が１個より多いempを抽出する
db.getCollection('emp').find({ $where: "this.hobby.length > 1" },
{ "emp_id" : "1001", "hobby" : [ "reading", "music" ] }
{ "emp_id" : "1002", "hobby" : [ "writing", "music" ] }
{ "emp_id" : "1003", "hobby" : [ "speaking", "music" ] }
{ "emp_id" : "1004", "hobby" : [ "teaching", "music" ] }
{ "emp_id" : "1005", "hobby" : [ "learning", "music" ] }
{ "emp_id" : "1006", "hobby" : [ "reading", "music" ] }
```

# 更新

####例①：emp_class="100"に対して、reflect_flg＝"0"を設定する

```
# emp_class="100"に対して、reflect_flg＝"0"を設定する
db.getCollection("emp").update(
 { "emp_class" : "100" },             // 更新条件
 { $set : { "reflect_flg" : "0" } },  // 更新データ
 { multi : true }  　　　　　　　　　 　// 複数行の更新指定
)

# emp_id, emp_class, reflect_flg列のみ表示し、全ての行を抽出しする
db.getCollection("emp").find({}, { "_id" : 0, "emp_id" : 1, "emp_class" : 1, "reflect_flg" : 1 })

＞結果
{ "emp_id" : "1001", "emp_class" : "100", "reflect_flg" : "0"}
{ "emp_id" : "1002", "emp_class" : "100", "reflect_flg" : "0"}
{ "emp_id" : "1003", "emp_class" : "100", "reflect_flg" : "0"}
{ "emp_id" : "1004", "emp_class" : "200"}
{ "emp_id" : "1005", "emp_class" : "200", "reflect_flg" : null}
{ "emp_id" : "1006", "emp_class" : "300", "reflect_flg" : "0"}
{ "emp_id" : "1007", "emp_class" : "300", "reflect_flg" : "0"}
{ "emp_id" : "1008", "emp_class" : "300", "reflect_flg" : "1"}
```

# グループ、カウント、SUM、MAX


### 例①：１項目のグループ

```
db.getCollection("emp").aggregate([
  {
    "$group" : { _id : "$emp_class" } // group can also for object field (eg. $details.Name")
  }])

＞結果
{ "_id" : "100"}
{ "_id" : "200"}
{ "_id" : "300"}
```
###例②：カウント

#### emp_classでグループした結果を出す

```
# skip, limit無し：全てのdocumentを出す
db.getCollection("emp").aggregate([
  {
    $group :
     {
　　　 _id : "$emp_class",
      total : { $sum : 1 }
 　　}
  }, 
  {"$sort"  : {"total" : 1} }
])

＞結果
{ "_id" : "200", "total" : 2.0 }
{ "_id" : "300", "total" : 3.0 }
{ "_id" : "100", "total" : 3.0 }
```

```
## skip, limit有り：２行目から５件出す
db.getCollection("emp").aggregate([
  {
    $group :
     {
　　　 _id : "$emp_class",
      total : { $sum : 1 }
 　　}
  }, 
  {"$sort"  : {"total" : 1} },
  {"$skip"  : 1 },
  {"$limit" : 5 }
])

＞結果
{ "_id" : "300", "total" : 3.0 }
{ "_id" : "100", "total" : 3.0 }
```

#### delete_flgが0に該当するdocumentから、emp_classでグループし、件数を出す

```
db.getCollection('emp').aggregate(
  [ {$match: {"delete_flg" : "0"} }, // can write many $match
    {$group: {"_id" : "$emp_class"} },
    {$count: "count"  }
  ])

＞結果
3
```


####例③：複数項目のグループ

```
db.getCollection("emp").aggregate([
  {
    $group :
     {
　　　 _id : 
       {
         "class" : "$emp_class",
         "reflectFlg" : "$reflect_flg"
      },
      total : { $sum : 1 }
 　　}
  }
])

＞結果
{ "_id" : { "class" : "100" },  "total" : 3.0 }
{ "_id" : { "class" : "200" },  "total" : 1.0 }
{ "_id" : { "class" : "200", "reflectFlg" : null },  "total" : 1.0 }
{ "_id" : { "class" : "300", "reflectFlg" : "0" },  "total" : 2.0 }
{ "_id" : { "class" : "300", "reflectFlg" : "1" },  "total" : 1.0 }
```

####例④：条件付きグループ

```
db.getCollection("emp").aggregate([
  { $match : { "delete_flg" : "0" } },
  {
    $group :
     {
　　　 _id : 
       {
         "class" : "$emp_class",
         "reflectFlg" : "$reflect_flg"
      },
      total : { $sum : 1 }
 　　}
  }
])

＞結果
{ "_id" : { "class" : "100" },  "total" : 3 }
{ "_id" : { "class" : "200" },  "total" : 1 }
{ "_id" : { "class" : "200", "reflectFlg" : null },  "total" : 1 }
{ "_id" : { "class" : "300", "reflectFlg" : "0" },  "total" : 1 }
{ "_id" : { "class" : "300", "reflectFlg" : "1" },  "total" : 1 }
```

####例⑤：max

```
db.getCollection("emp").aggregate([
  {
    $group :
     {
　　　 _id : 
       {
         "class" : "$emp_class",
         "reflectFlg" : "$reflect_flg"
      },
      total : { $sum : 1 },
      maxDate: { $max : "$create_date" }
 　　}
  }
])

＞結果
{ "_id" : { "class" : "100" },  "total" : 3, "maxDate" : "2021-03-01" }
{ "_id" : { "class" : "200" },  "total" : 1, "maxDate" : "2021-04-01" }
{ "_id" : { "class" : "200", "reflectFlg" : null },  "total" : 1, "maxDate" : "2021-05-01" }
{ "_id" : { "class" : "300", "reflectFlg" : "0" },  "total" : 2, "maxDate" : "2021-07-01" }
{ "_id" : { "class" : "300", "reflectFlg" : "1" },  "total" : 1, "maxDate" : "2021-08-01" }
```

####例⑥：ソート（maxDate降順）

```
db.getCollection("emp").aggregate([
  {
    $group :
     {
　　　 _id : 
       {
         "class" : "$emp_class",
         "reflectFlg" : "$reflect_flg"
      },
      total : { $sum : 1 },
      maxDate: { $max : "$create_date" }
 　　}
  },
  { $sort : { "maxDate" : -1 } },
  //{ $skip : 1 },
  //{ $limit : 2 },
])

＞結果
{ "_id" : { "class" : "300", "reflectFlg" : "1" },  "total" : 1, "maxDate" : "2021-08-01" }
{ "_id" : { "class" : "300", "reflectFlg" : "0" },  "total" : 2, "maxDate" : "2021-07-01" }
{ "_id" : { "class" : "200", "reflectFlg" : null },  "total" : 1, "maxDate" : "2021-05-01" }
{ "_id" : { "class" : "200" },  "total" : 1, "maxDate" : "2021-04-01" }
{ "_id" : { "class" : "100" },  "total" : 3, "maxDate" : "2021-03-01" }
```


####例⑦：全てのempの給料を足す

```
db.getCollection('emp').aggregate(
[{ $group: {
      _id: {},
     "total": {"$sum": "$salary"}} }
])

＞結果
{
    "_id" : {},
    "total" : NumberLong(29000)
}
```

####例⑧：新規フィールド（合計salary, strConcat = emp_name + " : " + emp_class）の追加

```
db.getCollection('emp').aggregate(
[ { $addFields : {
      "strConcat": {"$concat": [ "$emp_name", " : ","$emp_class" ] },
      "total": { $sum: [ "$salary"] }
   }},
   { $project : {"_id" : 0, "emp_id" : 1, "salary" : 1, "strConcat" : 1, "total" : 1} } // 出力フィールドの指定
])

＞結果
{ "emp_id" : "1001", "salary" : NumberLong(1000), "strConcat" : "Emp1 : 100", "total" : NumberLong(1000) }
{ "emp_id" : "1002", "salary" : NumberLong(2000), "strConcat" : "Emp2 : 100", "total" : NumberLong(2000) }
{ "emp_id" : "1003", "salary" : NumberLong(3000), "strConcat" : "Emp3 : 100", "total" : NumberLong(3000) }
{ "emp_id" : "1004", "salary" : NumberLong(4000), "strConcat" : "Emp4 : 200", "total" : NumberLong(4000) }
{ "emp_id" : "1005", "salary" : NumberLong(5000), "strConcat" : "Emp5 : 200", "total" : NumberLong(5000) }
{ "emp_id" : "1006", "salary" : NumberLong(6000), "strConcat" : "Emp6 : 300", "total" : NumberLong(6000) }
{ "emp_id" : "1007", "strConcat" : "Emp7 : 300", "total" : NumberLong(0) }
{ "emp_id" : "1008", "salary" : NumberLong(2000), "strConcat" : "Emp8 : 300", "total" : NumberLong(8000) }
```
# 同じDB内のCollectionの結合

```
# Employee DB内、emp_experience Collectionを作り、データ挿入する
db.getCollection('emp_experience').insertMany([
{
    "emp_id" : "1001",
    "experience" : ["Java"],
    "update_date" : ISODate("2020-12-31T09:00:00.000Z")
},
{
    "emp_id" : "1001",
    "experience" : ["Java", "PHP"],
    "update_date" : ISODate("2021-01-31T09:00:00.000Z")
},
{
    "emp_id" : "1002",
    "experience" : ["Python"],
    "update_date" : ISODate("2021-02-28T09:00:00.000Z")
},
{
    "emp_id" : "1003",
    "experience" : ["Java"],
    "update_date" : ISODate("2021-03-31T09:00:00.000Z")
}
])
```

### emp, emp_experience Collectionを結合した件数を出す

```
db.getCollection('emp_experience').aggregate(
[
  { $lookup : {
          from : "emp",
          let  : { exp_emp_id : "$emp_id" }, // emp_experience collection's emp_id
          pipeline : [
           { $match : {
                 $expr : {
                   $and : [ { $eq : [ "$emp_id", "$$exp_emp_id"] } ]
              } }
           }
         ],
         as : "emp"
      }      
  },
  {
   "$unwind": {"path": "$emp",
               "preserveNullAndEmptyArrays": false // true : will also print for not exist (field/ left join), false : inner join
  }},
  { $group: { _id: null, total: { $sum: 1 } } },
])
```

```
# 結果
{
    "_id" : null,
    "total" : 4.0
}
```


### emp, emp_experience Collectionを結合し、emp_idでグループした件数を出す

```
db.getCollection('emp_experience').aggregate(
[
  { $lookup : {
          from : "emp",
          let  : { exp_emp_id : "$emp_id" }, // emp_experience collection's emp_id
          pipeline : [
           { $match : {
                 $expr : {
                   $and : [ { $eq : [ "$emp_id", "$$exp_emp_id"] } ]
              } }
           }
         ],
         as : "emp"
      }      
  },
  {
   "$unwind": {"path": "$emp",
               "preserveNullAndEmptyArrays": false // true : will also print for not exist (field/ left join), false : inner join
  }},
  { $group: { _id: { "emp_id" : "$emp_id"}, total: { $sum: 1 } } },
])
```

```
# 結果
{ "_id" : {"emp_id" : "1003"　},　"total" : 1.0 }
{ "_id" : {"emp_id" : "1001"　},　"total" : 2.0 }
{ "_id" : {"emp_id" : "1002"　},　"total" : 1.0 }
```

### emp_experienceの更新日「2021-01-01」後のデータとempを結合した結果

```
db.getCollection('emp_experience').aggregate(
[
  { $match : { "update_date" : { $gt : ISODate("2021-01-01T09:00:00.000Z") } } },
  { $lookup : {
          from : "emp",
          let  : { exp_emp_id : "$emp_id" }, // emp_experience collection's emp_id
          pipeline : [
           { $match : {
                 $expr : {
                   $and : [ { $eq : [ "$emp_id", "$$exp_emp_id"] } ]
              } }
           }
         ],
         as : "emp"
      }      
  },
  {
   "$unwind": {"path": "$emp",
               "preserveNullAndEmptyArrays": false // true : will also print for not exist (field/ left join), false : inner join
  }},
  { "$project": {"_id" : 0, "emp_id" : 1, "experience" : 1 } }
 // { $group: { _id: null, total: { $sum: 1 } } },
])
```

```
# 結果
{ "emp_id" : "1001", "experience" : ["Java", "PHP"] }
{ "emp_id" : "1002", "experience" : ["Python"] }
{ "emp_id" : "1003", "experience" : ["Java"] }
```

### empとemp_experienceを結合し、「"emp_id" : "1001"」に該当するデータの全件と最初の10件を出す

##### 前提：emp_experienceに「"emp_id" : "1001"」のデータが30件存在とする。

```
db.getCollection('emp_experience').aggregate([
{"$match": {"$and": [{"emp_id": "1001"}] } },
{ "$facet" :{ 
    "metadata" :[{"$count": "total"}],
    "data" :[
      {"$lookup": {
                    "from": "emp", 
                    "let": {"emp_id": "$emp_id"}, 
                    "pipeline": [{"$match": {"$expr": {"$eq": ["$emp_id", "$$emp_id"]} } },
                                 { "$limit" :1 } ],
                    "as" :"document" } },
    {
      "$unwind" :{ 
        "path" :"$document",
        "preserveNullAndEmptyArrays" :false
      } },
    { "$sort" :{ "emp_id" :- 1 } },
    { "$skip" :0 },
    { "$limit" :10 }
   ]
  }
} ])
```

```
# 結果
{
    "metadata" : [{ "total" : 30 }],
    "data" : [  // 下記と同様の結合した最初の10件が出てくる
        { "_id" : ....,
          "emp_id" : "1001",
          "experience" : ....,
          "update_date" : ....,
          "document" : { // emp Collection's data
                         "_id" : ....,
                         "emp_id" : "1001",
                         "emp_name" : ....,
                         ...
                       }
        },
        ...
    ]
}
```

# 異なるDBのCollectionの更新コマンド

DB Name : EmployeeJob, Collection Name : emp_job

|_id|emp_id|emp_job_id|delete_flg|create_date|
|---|---|---|---|---|
|ObjectId(....1)|1001|100|0|2021-01-01|
|ObjectId(....2)|1002|100|0|2021-02-01|
|ObjectId(....3)|1003|100|0|2021-03-01|
|ObjectId(....4)|1004|200|0|2021-04-01|
|ObjectId(....5)|1005|200|0|2021-05-01|
|ObjectId(....6)|1006|300|0|2021-06-01|
|ObjectId(....6)|1007|300|0|2021-07-01|
|ObjectId(....6)|1008|300|0|2021-08-01|

> １．下記コマンドの内容の説明
Employee DBのemp Collectionの各データに対して、EmployeeJob DBのemp_job Collectionの下記列のデータを変更する。
「emp_job_id=100」の場合、「emp_job_id=1000」に変更
「emp_job_id=200」の場合、「emp_job_id=2000」に変更<br/>「emp_job_id=300」の場合、「emp_job_id=3000」に変更

```
// emp Collectionの各行に対して、ループする
db.getSiblingDB(“Employee”)
　.getCollection(“emp”)
 .find({})
 .forEach(function(row) {

　// emp_job_idにより、変更値を準備する
　var class = “”;
  if (row.emp_job_id == “100”) {
    class = “1000”;
  } else if (row.emp_job_id == “200”) {
    class = “2000”;
  } else if (row.emp_job_id == “300”) {
    class = “3000”;
  }

　// ログ出す
　print(“Update Data ：emp_id=” + row.emp_id + “, class=” + class);

  // 更新処理
　db.getSiblingDB(“EmployeeJob”)
　　.getCollection(“emp_job”)
　　.update({“emp_id” : row.emp_id},
　　　　　　　{“emp_job_id” : class});

})

// emp_id, emp_job_id列のみ表示し、全ての行を抽出しする
db.getCollection("emp_job").find({}, { "_id" : 0, "emp_id" : 1, "emp_job_id" : 1})
```

＞結果

```
{ "emp_id" : "1001", "emp_job_id" : "1000"}
{ "emp_id" : "1002", "emp_job_id" : "1000"}
{ "emp_id" : "1003", "emp_job_id" : "1000"}
{ "emp_id" : "1004", "emp_job_id" : "2000"}
{ "emp_id" : "1005", "emp_job_id" : "2000"}
{ "emp_id" : "1006", "emp_job_id" : "3000"}
{ "emp_id" : "1007", "emp_job_id" : "3000"}
{ "emp_id" : "1008", "emp_job_id" : "3000"}
```

> ２．下記コマンドの内容の説明
> Employee DBのempから３つのdocumentのemp_idを抽出する

```
db.emp.find().limit(3).forEach(doc => { 
    print(doc.emp_id);
 }
)

# 結果
1001
1002
1003

```

> ３．下記コマンドの内容の説明
> EmployeeJob DBのemp_jobの３つのemp_idに対して、Employee DBのempから抽出する

```
db.getSiblingDB("Employee").getCollection("emp").find({"emp_id": 
{ $in: db.getSiblingDB("EmployeeJob").getCollection("emp_job").find().limit(3).map(doc => doc.emp_id) }
}, {"_id" : 0, "emp_id" : 1, "emp_name" : 1} )
```

# 小さい処理

##### 「"hobby" : "reading"」に該当するemp_idを変数に格納する

```
var empIds = [];
db.getCollection('emp').find({"hobby" : "reading"}).forEach(function(emp){
   empIds.push("\"" + emp.emp_id + "\"");
});
for (var i = 0; i < empIds.length; i++) {
    print(empIds[i]);
}
print(empIds.length);
print(empIds.join(","));
```

```
# print(empIds[i])の結果
"1001"
"1006"
"1007"
```

```
# print(empIds.length)の結果
3
```

```
# print(empIds.join(","))の結果
"1001","1006","1007"
```

# function

### functionの作成
- 引数のemp_classに紐づくクラス名を取得する関数を作成する

```
> db.system.js.save({_id:'getEmpClassName', value:function (paramEmpClass) {
   var result = "";
   switch (paramEmpClass) {
     case "100" : result = "100Name"; break;
     case "200" : result = "200Name"; break;
     case "300" : result = "300Name"; break;
     default : result = "unknow";
   }
   return result;
   }
 });
```


### 登録functionの削除
```
db.system.js.remove({_id:'functionName'})
```

### 登録function一覧の取得
```
> db.getCollection('system.js').find({})
{
    "_id" : "getEmpClassName",
    "value" : function (paramEmpClass) {
                 var result = "";
                 switch (paramEmpClass) {
                   case "100" : result = "100Name"; break;
                   case "200" : result = "200Name"; break;
                   case "300" : result = "300Name"; break;
                   default : result = "unknow";
                 }
                 return result;
     }
}
```

### functionの呼び出し
- 引数のemp_classに紐づくクラス名を取得する関数を作成する

```
> db.loadServerScripts()
> getEmpClassName("100")
100Name

> getEmpClassName("200")
200Name

> getEmpClassName("300")
300Name

> getEmpClassName("400")
unknow

```

### 異なるDBのCollectionを元に、emp_idに紐づくemp_job_idを取得するfunction
```
# functionの作成
db.system.js.save({_id:'getJobId', value:function (paramEmpId) {
    db.getSiblingDB("Employee").getCollection("emp").find({"emp_id" : (paramEmpId) }).forEach(function(employee){
      db.getSiblingDB("EmployeeJob").getCollection("emp_job").find({"emp_id" : employee.emp_id }).forEach(function(employeeJob){
           print("\"emp_job_id\" : " + employeeJob.emp_job_id);
      });
    });
  }
});

# 実行結果
> db.loadServerScripts()
> getJobId("1001")
"emp_job_id" : 100

```

# dump/restore, export/import

```
# デフォルトbsonファイルのエクスポート
mongodump --host=localhost --port=27017 --db=dbName --out=C:\outputFolder

mongorestore --host=localhost --port=27017 --db=dbName C:\inputFolder\collectionName.bson
```

```
# ファイルタイプ指定して、エクスポートすることが可能
# csvまたはjsonファイルが出力可能（csvの場合は「--fields or --fieldFile」で出力対象フィールドを指定しなければならない）※

# 条件なしで、コレクションの全てのデータをエクスポートする
mongoexport --db=Employee -c=emp --limit=4 --fields=emp_id,emp_name --type=csv --out=C:\xxxxx\filename.csv

# windows＞条件付きでエクスポートする
mongoexport --db=Employee -c=emp --query="{ \"delete_flg\": \"0\" }" --limit=4 --fields=emp_id,emp_name --type=csv --out=C:\xxxxx\filename.csv

# linux＞条件付きでエクスポートする
mongoexport --db=Employee -c=emp --query='{"delete_flg":"0"}' --fields=enqueteName --type=csv --out=/tmp/xxx/filename.csv

# windows＞csvファイルのデータをインポートする
mongoimport --db=Employee -c=emp --fields=emp_id,emp_name,emp_class --type=csv --file=C:\xxxx\empData.csv

# linux＞csvファイルのデータをインポートする
mongoimport --db=Employee -c=emp --fields=emp_id,emp_name,emp_class --type=csv --file=/tmp/empData.csv

```
※オプションの詳しい説明は[こちら](https://www.mongodb.com/docs/database-tools/mongoexport/)を参照してください