1. 程式人生 > >MongoDB CRUD之U

MongoDB CRUD之U

cal bar json rdo item nts 3.4 tro mongo

文檔更新

命令 操作
db.collection.update(query, update, options) 修改集合中的現有文檔或文檔。
該方法可以根據更新參數修改現有文檔
或文檔的特定字段,
或完全替換現有文檔。
db.collection.updateMany(filter, update, options) 基於過濾器更新集合中的多個文檔。
db.collection.updateOne(filter, update, options) 根據過濾器更新集合中的單個文檔。
db.collection.replaceOne(filter, replacement, options
)
根據過濾器替換集合中的單個文檔。

更多參考

Update

格式

db.collection.update(
   <query>,
   <update>,
   {
     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ]
   }
)

全覆蓋更新

  • 不加任何參數
14 > db.set2test.find({ x: { $lt:10 } })
{ "_id" : ObjectId("5a7943273fdd5fec85460638"), "x" : 3 }
...
{ "_id" : ObjectId("5a7943273fdd5fec8546063e"), "x" : 9 }
15 > db.set2test.update({ x: { $lt:10 } }, { x: 999 })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
16 > db.set2test.find({ x: { $lt:10 } })
{ "_id" : ObjectId("5a7943273fdd5fec85460639"), "x" : 4 }
...
{ "_id" : ObjectId("5a7943273fdd5fec8546063e"), "x" : 9 }

會默認更新第一條匹配的數據.

21 > db.set2test.insert({
...      x : 3,
...      y : 4,
...      z : 5
... })
WriteResult({ "nInserted" : 1 })
22 > db.set2test.update({ x:3 }, { x:6, y:8, z:10 })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
23 > db.set2test.find( { z:10 } )
{ "_id" : ObjectId("5a798f6052866ce905d74021"), "x" : 6, "y" : 8, "z" : 10 }
24 > db.set2test.update({ x:6 }, { x:666 })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
25 > db.set2test.find( { x:666 } )
{ "_id" : ObjectId("5a7943273fdd5fec8546063b"), "x" : 666 }

可以看到不指定字段進行更新的話,會默認將所有的字段進行覆蓋,這樣的操作其實很危險.

部分更新

  • 使用循環和$set添加新的字段
29 > for(i = 3; i < 100; i++)db.set2test.update({ x:i }, { $set: { twice:i*2 } })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
30 > db.set2test.find()
{ "_id" : 5, "x" : 3, "twice" : 6 }
{ "_id" : 6, "x" : 4, "twice" : 8 }
{ "_id" : 7, "x" : 5, "twice" : 10 }
{ "_id" : 8, "x" : 6, "twice" : 12 }
{ "_id" : 9, "x" : 7, "twice" : 14 }
{ "_id" : 10, "x" : 8, "twice" : 16 }
{ "_id" : 11, "x" : 9, "twice" : 18 }
...

這樣就不會覆蓋所有的數據了.

  • 使用參數multi更新所有符合條件的數據和$unset刪除字段
34 > db.set2test.find({ x:10 })
{ "_id" : 5, "x" : 10, "twice" : "" }
{ "_id" : 6, "x" : 10, "twice" : "" }
{ "_id" : 7, "x" : 10, "twice" : "" }
{ "_id" : 8, "x" : 10, "twice" : "" }
{ "_id" : 9, "x" : 10, "twice" : "" }
{ "_id" : 10, "x" : 10, "twice" : "" }
{ "_id" : 11, "x" : 10, "twice" : "" }
{ "_id" : 12, "x" : 10, "twice" : 20 }
35 > db.set2test.update(
    { x:10 },
    { 
        $unset:{ twice: "" }, 
        $set:{ x:17 } 
        },
    { multi:true }
)
WriteResult({ "nMatched" : 8, "nUpserted" : 0, "nModified" : 8 })
36 > db.set2test.find({ x:17 })
{ "_id" : 5, "x" : 17 }
{ "_id" : 6, "x" : 17 }
{ "_id" : 7, "x" : 17 }
{ "_id" : 8, "x" : 17 }
{ "_id" : 9, "x" : 17 }
{ "_id" : 10, "x" : 17 }
{ "_id" : 11, "x" : 17 }
{ "_id" : 12, "x" : 17 }
{ "_id" : 19, "x" : 17, "twice" : 34 }

註: multi只能和$set使用

匹配不到時創建

  • 使用upsert
37 > db.books.find()
38 > db.books.update(
...     { item: "ZZZ135" },
...     {
...         item: "ZZZ135",
...         stock: 5,
...         tags: [ "database" ]
...     },
...     { upsert: true }
... )
WriteResult({
    "nMatched" : 0,
    "nUpserted" : 1,
    "nModified" : 0,
    "_id" : ObjectId("5a79977f8c823207073133c4")
})
39 > db.books.find()
{ "_id" : ..., "item" : "ZZZ135", "stock" : 5, "tags" : [ "database" ] }
  • 聯合使用參數multi和upsert
3 > db.books.find().pretty()
{
    "_id" : 5,
    "item" : "EFG222",
    "stock" : 18,
    "info" : {
        "publisher" : "0000",
        "pages" : 70
    },
    "reorder" : true
}
{
    "_id" : 6,
    "item" : "EFG222",
    "stock" : 15,
    "info" : {
        "publisher" : "1111",
        "pages" : 72
    },
    "reorder" : true
}

準備更新的js文檔:

db.books.update(
    { item: "EFG222" },
    { $set: { reorder: false, tags: [ "literature", "translated" ] } },
    { upsert: true, multi: true }
)

shell 中加載文檔

4 > load("query_books.js")
true
5 > db.books.find().pretty()
{
    "_id" : 5,
    "item" : "EFG222",
    "stock" : 18,
    "info" : {
        "publisher" : "0000",
        "pages" : 70
    },
    "reorder" : false,
    "tags" : [
        "literature",
        "translated"
    ]
}
{
    "_id" : 6,
    "item" : "EFG222",
    "stock" : 15,
    "info" : {
        "publisher" : "1111",
        "pages" : 72
    },
    "reorder" : false,
    "tags" : [
        "literature",
        "translated"
    ]
}
  • colllation指定排序
9 > db.mycoll0.find()
{ "_id" : 1, "category" : "café", "status" : "A" }
{ "_id" : 2, "category" : "cafe", "status" : "a" }
{ "_id" : 3, "category" : "cafE", "status" : "a" }

collation參數見這裏

準備的更新文檔如下

db.myColl.update(
   { category: "cafe" },
   { $set: { status: "Updated" } },
   { collation: { locale: "fr", strength: 1 } }
);

加載js文檔

10 > load("updata_mycoll9.js")
true
11 > db.mycoll0.find()
{ "_id" : 1, "category" : "café", "status" : "A" }
{ "_id" : 2, "category" : "cafe", "status" : "a" }
{ "_id" : 3, "category" : "cafE", "status" : "a" }
  • 使用參數arrayFilter更新數組(New in version 3.6.)
15 > db.students.find()
{ "_id" : 1, "grades" : [ 95, 92, 90 ] }
{ "_id" : 2, "grades" : [ 98, 100, 102 ] }
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }

準備的更新文檔如下

db.students.update(
   { grades: { $gte: 100 } },
   { $set: { "grades.$[element]" : 100 } },
   {
     multi: true,
     arrayFilters: [ { "element": { $gte: 100 } } ]
   }
)

加載js文檔

23 > load("update_students.js")
true

因為我的版本是3.4,所以不會生效

正常變更後的數據為:

{ "_id" : 1, "grades" : [ 95, 92, 90 ] }
{ "_id" : 2, "grades" : [ 98, 100, 100 ] }
{ "_id" : 3, "grades" : [ 95, 100, 100 ] }

這是來自官網的教程 , 只能以後再看略.

updateOne

格式

db.collection.updateOne(
   <filter>,
   <update>,
   {
     upsert: <boolean>,
     writeConcern: <document>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ]
   }
)

可以看到參數與Update一樣的,但顧名思義的應該是只能更新一條數據

使用參數upsert

數據

27 > load("data_restaurant.js")
true
28 > db.restaurant.find()
{ "_id" : 1, "name" : "Central Perk Cafe", "Borough" : "Manhattan", "violations" : 3 }
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "Borough" : "Queens", "violations" : 2 }
{ "_id" : 3, "name" : "Empire State Pub", "Borough" : "Brooklyn", "violations" : "0" }

操作

29 > try {
...    db.restaurant.updateOne(
...       { "name" : "Pizza Rat's Pizzaria" },
...       { $set: {"_id" : 4, "violations" : 7, "borough" : "Manhattan" } },
...       { upsert: true }
...    );
... } catch (e) {
...    print(e);
... }
{
    "acknowledged" : true,
    "matchedCount" : 0,
    "modifiedCount" : 0,
    "upsertedId" : 4
}
30 > db.restaurant.find()
{ "_id" : 1, "name" : "Central Perk Cafe", "Borough" : "Manhattan", "violations" : 3 }
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "Borough" : "Queens", "violations" : 2 }
{ "_id" : 3, "name" : "Empire State Pub", "Borough" : "Brooklyn", "violations" : "0" }
{ "_id" : 4, "name" : "Pizza Rat's Pizzaria", "violations" : 7, "borough" : "Manhattan" }

將違規10次以上的餐飲進行關停

31 > try {
...    db.restaurant.updateOne(
...       { "violations" : { $gt: 10} },
...       { $set: { "Closed" : true } },
...       { upsert: true }
...    );
... } catch (e) {
...    print(e);
... }
{
    "acknowledged" : true,
    "matchedCount" : 0,
    "modifiedCount" : 0,
    "upsertedId" : ObjectId("5a79c54fcf6c4175a57b2bff")
}
32 > db.restaurant.find()
{ "_id" : 1, "name" : "Central Perk Cafe", "Borough" : "Manhattan", "violations" : 3 }
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "Borough" : "Queens", "violations" : 2 }
{ "_id" : 3, "name" : "Empire State Pub", "Borough" : "Brooklyn", "violations" : "0" }
{ "_id" : 4, "name" : "Pizza Rat's Pizzaria", "violations" : 7, "borough" : "Manhattan" }
{ "_id" : ObjectId("5a79c54fcf6c4175a57b2bff"), "Closed" : true }

updataMany

格式

db.collection.updateMany(
   <filter>,
   <update>,
   {
     upsert: <boolean>,
     writeConcern: <document>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ]
   }
)

無參更新

39 > db.restaurant.find()
{ "_id" : 1, "name" : "Central Perk Cafe", "violations" : 3 }
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "violations" : 2 }
{ "_id" : 3, "name" : "Empire State Sub", "violations" : 5 }
{ "_id" : 4, "name" : "Pizza Rat's Pizzaria", "violations" : 8 }
40 > try {
...    db.restaurant.updateMany(
...       { violations: { $gt: 4 } },
...       { $set: { "Review" : true } }
...    );
... } catch (e) {
...    print(e);
... }
{ "acknowledged" : true, "matchedCount" : 2, "modifiedCount" : 2 }
41 > db.restaurant.find()
{ "_id" : 1, "name" : "Central Perk Cafe", "violations" : 3 }
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "violations" : 2 }
{ "_id" : 3, "name" : "Empire State Sub", "violations" : 5, "Review" : true }
{ "_id" : 4, "name" : "Pizza Rat's Pizzaria", "violations" : 8, "Review" : true }

可以看到違規4次以上的餐飲將進行復查

使用參數upsert

43 > db.inspectors.find()
{ "_id" : 92412, "inspector" : "F. Drebin", "Sector" : 1, "Patrolling" : true }
{ "_id" : 92413, "inspector" : "J. Clouseau", "Sector" : 2, "Patrolling" : false }
{ "_id" : 92414, "inspector" : "J. Clouseau", "Sector" : 3, "Patrolling" : true }
{ "_id" : 92415, "inspector" : "R. Coltrane", "Sector" : 3, "Patrolling" : false }
44 > try {
...    db.inspectors.updateMany(
...       { "Sector" : { $gt : 4 }, "inspector" : "R. Coltrane" },
...       { $set: { "Patrolling" : false } },
...       { upsert: true }
...    );
... } catch (e) {
...    print(e);
... }
{
    "acknowledged" : true,
    "matchedCount" : 0,
    "modifiedCount" : 0,
    "upsertedId" : ObjectId("5a79c792cf6c4175a57b2c12")
}
45 > db.inspectors.find()
{ "_id" : 92412, "inspector" : "F. Drebin", "Sector" : 1, "Patrolling" : true }
{ "_id" : 92413, "inspector" : "J. Clouseau", "Sector" : 2, "Patrolling" : false }
{ "_id" : 92414, "inspector" : "J. Clouseau", "Sector" : 3, "Patrolling" : true }
{ "_id" : 92415, "inspector" : "R. Coltrane", "Sector" : 3, "Patrolling" : false }
{ "_id" : ObjectId("....."), "inspector" : "R. Coltrane", "Patrolling" : false }

replaceOne

格式

db.collection.replaceOne(
   <filter>,
   <replacement>,
   {
     upsert: <boolean>,
     writeConcern: <document>,
     collation: <document>
   }
)

這一條命令會取代原文檔

無參更新

> db.restaurant.find()
{ "_id" : 1, "name" : "Central Perk Cafe", "violations" : 3 }
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "violations" : 2 }
{ "_id" : 3, "name" : "Empire State Sub", "violations" : 5 }
{ "_id" : 4, "name" : "Pizza Rat's Pizzaria", "violations" : 8 }
> try {
...    db.restaurant.replaceOne(
...       { "name" : "Central Perk Cafe" },
...       { "name" : "Central Pork Cafe", "Borough" : "Manhattan" }
...    );
... } catch (e){
...    print(e);
... }
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.restaurant.find()
{ "_id" : 1, "name" : "Central Pork Cafe", "Borough" : "Manhattan" }
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "violations" : 2 }
{ "_id" : 3, "name" : "Empire State Sub", "violations" : 5 }
{ "_id" : 4, "name" : "Pizza Rat's Pizzaria", "violations" : 8 }

使用參數upsert

> db.restaurant.find()
{ "_id" : 1, "name" : "Central Perk Cafe", "violations" : 3 }
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "violations" : 2 }
{ "_id" : 3, "name" : "Empire State Sub", "violations" : 5 }
> try {
...    db.restaurant.replaceOne(
...       { "name" : "Pizza Rat's Pizzaria" },
...       { "_id": 4, "name" : "Pizza Rat's Pizzaria", "Borough" : "Manhattan", "violations" : 8 },
...       { upsert: true }
...    );
... } catch (e){
...    print(e);
... }
{
    "acknowledged" : true,
    "matchedCount" : 0,
    "modifiedCount" : 0,
    "upsertedId" : 4
}
> db.restaurant.find()
{ "_id" : 1, "name" : "Central Perk Cafe", "violations" : 3 }
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "violations" : 2 }
{ "_id" : 3, "name" : "Empire State Sub", "violations" : 5 }
{ "_id" : 4, "name" : "Pizza Rat's Pizzaria", "Borough" : "Manhattan", "violations" : 8 }

其他參數先不看吧,似乎很多是3.6!!

MongoDB CRUD之U