批次新增
  • 一次送出多筆資料會比逐筆新增來得快
  • 可以用命令列工具 mongoimport 來匯入資料,不用一直呼叫 insertMany
  • Message size can’t be larger than 48 MB
> db.movies.insertMany([{"title":"Movie 1"},{"title":"Movie 2"},{"title":"Movie 3"}])
{
    "acknowledged" : true,
    "insertedIds" : [
        ObjectId("5f6876732fbc27989eb7f4c2"),
        ObjectId("5f6876732fbc27989eb7f4c3"),
        ObjectId("5f6876732fbc27989eb7f4c4")
    ]
}

有序與無序新增
有序新增(預設):只要有一筆資料新增失敗,MongoDB 就會停止後續的新增
無序新增:不管有沒有失敗,MongoDB 都會嘗試新增所有資料,無序新增的效能會比較好

刪除集合 
ex. db.movies.drop()
> db.movies.insertOne(movie2)
{
        "acknowledged" : true,
        "insertedId" : ObjectId("5f68e75e85d32460c3bfa6e3")
}
> db.movies.find().pretty()
{
        "_id" : ObjectId("5f68e75885d32460c3bfa6e2"),
        "title" : "A movie",
        "director" : "A director",
        "year" : 2020
}
{
        "_id" : ObjectId("5f68e75e85d32460c3bfa6e3"),
        "title" : "A movie 2",
        "director" : "A director 2",
        "year" : 2020
}
> db.movies.drop()
true
> db.movies.find().pretty()

更新
更新看起來是原子操作,但我好奇如果兩個更新操作同時發生,而第二個操作的篩選條件因為第一個操作修改了資料而不再符合,會發生什麼事?
> db.movies.find().pretty()
{
        "_id" : ObjectId("5f6950a694d2d7702605f470"),
        "title" : "A movie",
        "director" : "A director",
        "year" : 2020
}
{
        "_id" : ObjectId("5f6950a794d2d7702605f471"),
        "title" : "A movie 2",
        "director" : "A director 2",
        "year" : 2020
}

// Update one movie
> db.movies.updateOne({"title":"A movie"},{$set:{"year":2021,"review":0}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.movies.find({"title":"A movie"}).pretty()
{
        "_id" : ObjectId("5f6950a694d2d7702605f470"),
        "title" : "A movie",
        "director" : "A director",
        "year" : 2021,
        "review" : 0
}

替換
replace 指令會替換整個文件
> db.movies.replaceOne({"title":"A movie"}, {"title":"B movie", "year":1990})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

> db.movies.find().pretty()
{
        "_id" : ObjectId("5f6950a694d2d7702605f470"),
        "title" : "B movie",
        "year" : 1990
}
{
        "_id" : ObjectId("5f6950a794d2d7702605f471"),
        "title" : "A movie 2",
        "director" : "A director 2",
        "year" : 2020
}

遞增一個數值
// create page document
> pageA= {"page":"page A", "view":0}
{ "page" : "page A", "view" : 0 }
> db.page.insertOne(pageA)
{
        "acknowledged" : true,
        "insertedId" : ObjectId("5f69551d94d2d7702605f472")
}

// check data
> db.page.find({"page":"page A"}).pretty()
{
        "_id" : ObjectId("5f69551d94d2d7702605f472"),
        "page" : "page A",
        "view" : 0
}

// increment
> db.page.updateOne({"page":"page A"},{"$inc":{"view":1}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

// check result
> db.page.find({"page":"page A"}).pretty()
{
        "_id" : ObjectId("5f69551d94d2d7702605f472"),
        "page" : "page A",
        "view" : 1
}

$unset
// check there is a view property
> db.page.find().pretty()
{
        "_id" : ObjectId("5f69551d94d2d7702605f472"),
        "page" : "page A",
        "view" : 1
}

// unset view property
> db.page.updateOne({"page":"page A"},{"$unset":{"view":1}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

// check view property disappeared
> db.page.find().pretty()
{ "_id" : ObjectId("5f69551d94d2d7702605f472"), "page" : "page A" }

$set 修改內嵌文件的屬性值
// set new property: user
> db.page.updateOne({"page":"page A"}, {"$set":{
...    "user":{
...      "display_name":"",
...      "devices":[
...
...      ],
...      "subscriptions":{
...          "vpn":{
...            "active":true,
...          }
...      },
...      "max_devices":5
...    },
... }})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

// check data
> db.page.find().pretty()
{
        "_id" : ObjectId("5f69551d94d2d7702605f472"),
        "page" : "page A",
        "user" : {
                "display_name" : "",
                "devices" : [ ],
                "subscriptions" : {
                        "vpn" : {
                                "active" : true
                        }
                },
                "max_devices" : 5
        }
}

// change display_name
> db.page.updateOne({"page":"page A"},{"$set":{"user.display_name":"ABCDE"}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

// check update result
> db.page.find().pretty()
{
        "_id" : ObjectId("5f69551d94d2d7702605f472"),
        "page" : "page A",
        "user" : {
                "display_name" : "ABCDE",
                "devices" : [ ],
                "subscriptions" : {
                        "vpn" : {
                                "active" : true
                        }
                },
                "max_devices" : 5
        }
}

$push 新增資料到陣列屬性
// push data to array attribute
> db.page.updateOne({"page":"page A"},{"$push":{"comment":"hello"}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.page.updateOne({"page":"page A"},{"$push":{"comment":"hello2"}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

// check result
> db.page.find().pretty()
{
        "_id" : ObjectId("5f69551d94d2d7702605f472"),
        "page" : "page A",
        "comment" : [
                "hello",
                "hello2"
        ]
}

用 $each 搭配 $push 新增多個元素到陣列屬性
// Can't add multiple elements to an array by simply $push
> db.page.updateOne({"page":"page A"},{"$push":{"comment":["hello3","hello4"]}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

// Because only $push will add only one element, thus one element with array value will be added
> db.page.find().pretty()
{
        "_id" : ObjectId("5f69551d94d2d7702605f472"),
        "page" : "page A",
        "comment" : [
                "hello",
                "hello2",
                [
                        "hello3",
                        "hello4"
                ]
        ]
}

// Need $each to add multiple elements
> db.page.updateOne({"page":"page A"},{"$push":{"comment":{"$each":["hello3","hello4"]}}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

> db.page.find().pretty()
{
        "_id" : ObjectId("5f69551d94d2d7702605f472"),
        "page" : "page A",
        "comment" : [
                "hello",
                "hello2",
                [
                        "hello3",
                        "hello4"
                ],
                "hello3",
                "hello4"
        ]
}

執行 $each 時用 $slice 把陣列切成 3 個元素
> db.page.updateOne({"page":"page A"},{"$push":{"comment":{"$each":[],"$slice":-3}}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

// rest 3 records
> db.page.find().pretty()
{
        "_id" : ObjectId("5f69551d94d2d7702605f472"),
        "page" : "page A",
        "comment" : [
                [
                        "hello3",
                        "hello4"
                ],
                "hello3",
                "hello4"
        ]
}


$slice 時同時 $sort
> db.page.updateOne({"page":"page A"},{"$push":{"top3":{"$each":[{"name":"A","height":5},{"name":"B","height":4},{"name":"C","height":3},{"name":"D","height":2},{"name":"E","height":1}],"$slice":-3,"$sort":{"height":1}}}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

> db.page.find().pretty()
{
        "_id" : ObjectId("5f69551d94d2d7702605f472"),
        "page" : "page A",
        "comment" : [
                "hello3",
                "hello4"
        ],
        "top3" : [
                {
                        "name" : "C",
                        "height" : 3
                },
                {
                        "name" : "B",
                        "height" : 4
                },
                {
                        "name" : "A",
                        "height" : 5
                }
        ]
}

$push 留言
> db.users.updateOne({"name":"user1"},{"$push":{"comment":{"email":"a@gmail.com"}}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

> db.users.updateOne({"name":"user1"},{"$push":{"comment":{"email":"b@gmail.com"}}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

> db.users.find().pretty()
{
        "_id" : ObjectId("5f6a38748074fb4051b75cb8"),
        "name" : "user1",
        "comment" : [
                {
                        "email" : "a@gmail.com"
                },
                {
                        "email" : "b@gmail.com"
                }
        ]
}

$push 之後再用 $addToSet 搭配 $each 加入電話
> user = {"name":"user 1"}
{ "name" : "user 1" }
> db.users.insertOne(user)
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5f6c46393c90a681c72b7df5")
}

> db.users.updateOne({"name":"user 1"},{$push:{"phone":"123456"}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

> db.users.find().pretty()
{
    "_id" : ObjectId("5f6c46393c90a681c72b7df5"),
    "name" : "user 1",
    "phone" : [
        "123456"
    ]
}

// add existing phone, no modification
> db.users.updateOne({"name":"user 1"}, {"$addToSet":{"phone": "123456"}})
{ "acknowledged" : true, “matchedCount" : 1, "modifiedCount" : 0 }

// add new phone
> db.users.updateOne({"name":"user 1"}, {"$addToSet":{"phone": "223456"}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.users.find().pretty()
{
    "_id" : ObjectId("5f6c46393c90a681c72b7df5"),
    "name" : "user 1",
    "phone" : [
        "123456",
        "223456"
    ]
}

// add existing phone, no modification
> db.users.updateOne({"name":"user 1"}, {"$addToSet":{"phone": "223456"}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 0 }

// add multiple elements by $each, one non-existing phone, so one modification
> db.users.updateOne({"name":"user 1"}, {"$addToSet":{"phone": {"$each":["223456","12345"]}}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

> db.users.updateOne({"name":"user 1"}, {"$addToSet":{"phone": {"$each":["223456","12345","123456"]}}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 0 }
> db.users.find().pretty()
{
    "_id" : ObjectId("5f6c46393c90a681c72b7df5"),
    "name" : "user 1",
    "phone" : [
        "123456",
        "223456",
        "12345"
    ]
}


用 $pop 移除元素,$pop 1 從尾端移除,$pop -1 從開頭移除
> db.users.updateOne({"name":"user 1"}, {"$pop":{"phone": 1}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.users.find().pretty()
{
    "_id" : ObjectId("5f6c46393c90a681c72b7df5"),
    "name" : "user 1",
    "phone" : [
        "123456",
        "223456"
    ]
}

> db.users.updateOne({"name":"user 1"}, {"$pop":{"phone": -1}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.users.find().pretty()
{
    "_id" : ObjectId("5f6c46393c90a681c72b7df5"),
    "name" : "user 1",
    "phone" : [
        "223456"
    ]
}

用 $pull 移除元素
// pull element but value is not matched, no modification
> db.users.updateOne({"name":"user 1"}, {"$pull":{"phone":"123456"}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 0 }

//
> db.users.updateOne({"name":"user 1"}, {"$pull":{"phone":"223456"}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

> db.users.find().pretty()
{
    "_id" : ObjectId("5f6c46393c90a681c72b7df5"),
    "name" : "user 1",
    "phone" : [ ]
}

用 $pull 移除多個元素
// push elements
> db.users.updateOne({"name":"user 1"}, {"$addToSet":{"phone": {"$each":["223456","12345","123456"]}}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.users.find().pretty()
{
    "_id" : ObjectId("5f6c46393c90a681c72b7df5"),
    "name" : "user 1",
    "phone" : [
        "223456",
        "12345",
        "123456"
    ]
}
> db.users.updateOne({"name":"user 1"}, {$push:{"phone": {"$each":["223456","12345","123456"]}}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.users.find().pretty()
{
    "_id" : ObjectId("5f6c46393c90a681c72b7df5"),
    "name" : "user 1",
    "phone" : [
        "223456",
        "12345",
        "123456",
        "223456",
        "12345",
        "123456"
    ]
}

// pull 123456, all 123456 will be removed
> db.users.updateOne({"name":"user 1"}, {"$pull":{"phone":"123456"}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.users.find().pretty()
{
    "_id" : ObjectId("5f6c46393c90a681c72b7df5"),
    "name" : "user 1",
    "phone" : [
        "223456",
        "12345",
        "223456",
        "12345"
    ]
}

$inc 遞增指定陣列索引的值
// original data
> db.users.find().pretty()
{
    "_id" : ObjectId("5f6c46393c90a681c72b7df5"),
    "name" : "user 1",
    "phone" : [
        "223456",
        "12345",
        "223456",
        "12345"
    ]
}

// push 2 comments
> db.users.updateOne({"name":"user 1"}, {$push:{"comment":{"vote":0,"message":"haha"}}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.users.updateOne({"name":"user 1"}, {$push:{"comment":{"vote":0,"message":"haha 2"}}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.users.find().pretty()
{
    "_id" : ObjectId("5f6c46393c90a681c72b7df5"),
    "name" : "user 1",
    "phone" : [
        "223456",
        "12345",
        "223456",
        "12345"
    ],
    "comment" : [
        {
            "vote" : 0,
            "message" : "haha"
        },
        {
            "vote" : 0,
            "message" : "haha 2"
        }
    ]
}

// increase the first element vote
> db.users.updateOne({"name":"user 1"}, {"$inc":{"comment.0.vote":1}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.users.find().pretty()
{
    "_id" : ObjectId("5f6c46393c90a681c72b7df5"),
    "name" : "user 1",
    "phone" : [
        "223456",
        "12345",
        "223456",
        "12345"
    ],
    "comment" : [
        {
            "vote" : 1,
            "message" : "haha"
        },
        {
            "vote" : 0,
            "message" : "haha 2"
        }
    ]
}

// increase 100 to the second element
> db.users.updateOne({"name":"user 1"}, {"$inc":{"comment.1.vote":100}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.users.find().pretty()
{
    "_id" : ObjectId("5f6c46393c90a681c72b7df5"),
    "name" : "user 1",
    "phone" : [
        "223456",
        "12345",
        "223456",
        "12345"
    ],
    "comment" : [
        {
            "vote" : 1,
            "message" : "haha"
        },
        {
            "vote" : 100,
            "message" : "haha 2"
        }
    ]
}

// update message when array element match arrayFilters
> db.users.updateOne({"name":"user 1"}, {$set:{"comment.$[elmt].message":"Good"}},{arrayFilters:[{"elmt.vote":{$lte: 11}}]})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

> db.users.find().pretty()
{
    "_id" : ObjectId("5f6c46393c90a681c72b7df5"),
    "name" : "user 1",
    "phone" : [
        "223456",
        "12345",
        "223456",
        "12345"
    ],
    "comment" : [
        {
            "vote" : 1,
            "message" : "Good"
        },
        {
            "vote" : 100,
            "message" : "haha 2"
        }
    ]
}

upsert:存在就更新,不存在就新增
// upsert age to user 1
> db.users.updateOne({"name":"user 1"},{"$set":{"age":10}},{"upsert":true})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.users.find().pretty()
{
    "_id" : ObjectId("5f6c46393c90a681c72b7df5"),
    "name" : "user 1",
    "phone" : [
        "223456",
        "12345",
        "223456",
        "12345"
    ],
    "comment" : [
        {
            "vote" : 1,
            "message" : "Good"
        },
        {
            "vote" : 100,
            "message" : "haha 2"
        }
    ],
    "age" : 10
}

// upsert age to user 2
> db.users.updateOne({"name":"user 2"},{"$set":{"age":10}},{"upsert":true})
{
    "acknowledged" : true,
    "matchedCount" : 0,
    "modifiedCount" : 0,
    "upsertedId" : ObjectId("5f6d6fa0d8c8c1bae1785718")
}
> db.users.find().pretty()
{
    "_id" : ObjectId("5f6c46393c90a681c72b7df5"),
    "name" : "user 1",
    "phone" : [
        "223456",
        "12345",
        "223456",
        "12345"
    ],
    "comment" : [
        {
            "vote" : 1,
            "message" : "Good"
        },
        {
            "vote" : 100,
            "message" : "haha 2"
        }
    ],
    "age" : 10
}
{
    "_id" : ObjectId("5f6d6fa0d8c8c1bae1785718"),
    "name" : "user 2",
    "age" : 10
}

$setOnInsert 在新增時設定屬性
// set createdAt when insert
> db.users.updateOne({"name":"user 2"},{"$setOnInsert":{"createdAt":new Date()}},{"upsert":true})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 0 }
> db.users.find().pretty()
{
    "_id" : ObjectId("5f6c46393c90a681c72b7df5"),
    "name" : "user 1",
    "phone" : [
        "223456",
        "12345",
        "223456",
        "12345"
    ],
    "comment" : [
        {
            "vote" : 1,
            "message" : "Good"
        },
        {
            "vote" : 100,
            "message" : "haha 2"
        }
    ],
    "age" : 10
}
{
    "_id" : ObjectId("5f6d6fa0d8c8c1bae1785718"),
    "name" : "user 2",
    "age" : 10
}

// 
> db.users.updateOne({"name":"user 3"},{"$setOnInsert":{"createdAt":new Date()}},{"upsert":true})
{
    "acknowledged" : true,
    "matchedCount" : 0,
    "modifiedCount" : 0,
    "upsertedId" : ObjectId("5f6d738ed8c8c1bae1785730")
}
> db.users.find().pretty()
{
    "_id" : ObjectId("5f6c46393c90a681c72b7df5"),
    "name" : "user 1",
    "phone" : [
        "223456",
        "12345",
        "223456",
        "12345"
    ],
    "comment" : [
        {
            "vote" : 1,
            "message" : "Good"
        },
        {
            "vote" : 100,
            "message" : "haha 2"
        }
    ],
    "age" : 10
}
{
    "_id" : ObjectId("5f6d6fa0d8c8c1bae1785718"),
    "name" : "user 2",
    "age" : 10
}
{
    "_id" : ObjectId("5f6d738ed8c8c1bae1785730"),
    "name" : "user 3",
    "createdAt" : ISODate("2020-09-25T04:35:26.398Z")
}

findOneAndUpdate 可以處理 race condition,但預設回傳的是修改前的舊文件。 
可以用 returnNewDocument 來回傳修改後的文件
// update and return old document
> db.users.findOneAndUpdate({"name":"user1"},{"$push":{"phone":{"$each":["123456"]}}})
{
        "_id" : ObjectId("5f6a38748074fb4051b75cb8"),
        "name" : "user1",
        "comment" : [
                {
                        "email" : "a@gmail.com"
                },
                {
                        "email" : "b@gmail.com"
                }
        ]
}

// update and return new document
> db.users.findOneAndUpdate({"name":"user1"},{"$push":{"phone":{"$each":["1234567"]}}},{"returnNewDocument":true})
{
        "_id" : ObjectId("5f6a38748074fb4051b75cb8"),
        "name" : "user1",
        "comment" : [
                {
                        "email" : "a@gmail.com"
                },
                {
                        "email" : "b@gmail.com"
                }
        ],
        "phone" : [
                "123456",
                "1234567"
        ]
}




Tags:

Updated: