MongoDB 4.X CRUD基本操作
mangoDB
目錄
建立(Create Operations)
db.collection.insert()
db.collection.insertOne()
db.collection.insertMany()
關于傳回确認資訊
查詢(Read Operations)
db.collection.find()
db.collection.findOne()
條件查詢操作符
更新(Update Operations)
db.collection.update()
db.collection.updateOne()
db.collection.updateMany()
删除(Delete Operations)
db.collection.deleteOne()
db.collection.deleteMany()
總結
參考
正文
本文總結了MongoDB 4.X在mongo shell用戶端涉及的對文檔一些基本的增删改查操作,即CRUD操作。主要結合了自己平時使用MongoDB的操作指令,更詳細的指令可以參考官方文檔:
https://docs.mongodb.com/manual/crud/。
回到頂部
建立(Create Operations)也叫插入操作,當集合不存在時,插入操作同時也會建立集合。MongoDB提供以下幾種插入文檔方法:
db.collection.insert():在指定集合中插入單個或多個文檔。
db.collection.insertOne():在指定集合中插入單個文檔(版本3.2新增)。
db.collection.insertMany():在指定集合中插入多個文檔(版本3.2新增)。
在平時的使用當中,db.collection.insert()是我用得最多的文檔插入方式,具體的文法格式如下:
db.collection.insert(
,
{
writeConcern: <document>,
ordered: <boolean>
}
)
參數說明:
document:指定一個或多個文檔;
writeConcern:文檔寫入确認級别(可選),關于讀寫政策确認級别,以後再進行讨論;
ordered:指定文檔是否按順序插入(可選),預設為true;
當指定為true時,插入多個文檔時将文檔排序儲存在一個數組中進行插入,如果其中有一個文檔插入失敗,則會導緻數組中餘下的文檔不進行插入操作;
當指定為false時,插入多個文檔時将文檔不進行排序儲存在一個數組中進行插入,如果其中有一個文檔插入失敗,則不影響數組中餘下的文檔進行插入操作。
如果插入的文檔當中沒有指定_id字段,則MongoDB會自動為文檔生成具有唯一ObjectId值的字段_id。
使用示例:
// 沒有指定_id字段的插入單個文檔
db.products.insert( { item: "card", qty: 15 } );
// 指定_id字段的插入單個文檔
db.products.insert( { _id: 10, item: "box", qty: 20 } );
// 插入多個文檔,不進行排序,多個文檔包含在數組[]中
db.products.insert(
[
{ _id: 11, item: "pencil", qty: 50, type: "no.2" },
{ item: "pen", qty: 20 },
{ item: "eraser", qty: 25 }
]
);
// 插入多個文檔,并進行排序
{ _id: 20, item: "lamp", qty: 50, type: "desk" },
{ _id: 21, item: "lamp", qty: 20, type: "floor" },
{ _id: 22, item: "bulk", qty: 100 }
],
{ ordered: false }
文法格式如下:
db.collection.insertOne(
writeConcern: <document>
參考db.collection.insert()的參數說明。
// 單行插入文檔,關于_id字段指定與否也與db.collection.insert()一緻
db.products.insertOne( { item: "card", qty: 15 } );
db.collection.insertMany(
[ , , ... ],
writeConcern: <document>,
ordered: <boolean>
db.collection.insert()在插入文檔成功之後傳回的資訊相對較為簡潔:
WriteResult({ "nInserted" : 1, "writeConcernError" : [ ] })
db.collection.insertOne()和db.collection.insertMany()傳回的資訊較為詳細:
{
"acknowledged": true,
"insertedId": ObjectId("5eccbd214139000074003be8")
db.products.insertMany( [
{ _id: 10, item: "large box", qty: 20 },
{ _id: 11, item: "small box", qty: 55 },
{ _id: 12, item: "medium box", qty: 30 }
] );
"acknowledged": true,
"insertedIds": [
10,
11,
12
]
查詢(Read Operations)讀操作,是對集合中已存在的文檔進行查詢,即對應關系型資料庫當中的select操作,比如MySQL,MongoDB提供以下幾種主要查詢文檔方法:
db.collection.find():查詢指定集合中滿足條件的一個或多個文檔和視圖;
db.collection.findOne():查詢指定集合中滿足條件的第一個文檔,并以格式化方式展現,通過pretty()方法。
來自官方文檔的測試資料:
db.inventory.insertMany([
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "A" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" }
]);
db.collection.find()可以說是使用頻率最高的方法了,可以用來查詢資料庫集合當中的文檔。
db.collection.find(, )
query:查詢表達式;
projection:指定查詢結果集中需要顯示的字段。
Col_name:1|true 代表顯示該字段;
Col_name:0 | false 代表不顯示該字段。
_id字段是預設顯示的,如果不想顯示,則顯式指定{"_id" : 0}。
查詢所有文檔:
db.inventory.find()
或
db.inventory.find({})
db.collection.findOne()方法顯示符合條件查詢的第一條文檔,接受的參數與db.collection.find()方法一緻。
通常對文檔的查詢,是需要帶條件的,而很少使用到不帶條件的全文檔檢索,以下總結了幾種常使用的查詢操作符:
比較操作符
比較操作符涉及的操作如下表所示:
名稱 說明
$eq 與指定值相等
$gt 大于指定的值
$gte 大于或等于指定的值
$in 指定的值在數組中
$lt 小于指定的值
$lte 小于或等于指定的值
$ne 所有不等于指定的值
$nin 指定的值不在數組中
// $eq:等值查詢 SQL: SELECT * FROM inventory WHERE status = "D";
db.inventory.find( { status: "D" } )
// $ne 同$eq
// $gt:範圍查詢(以大于為例) SQL: SELECT * FROM inventory WHERE qty > 30;
db.inventory.find( { qty: { $gt: 30 } } )
// $gte、$lt、$lte 同$gt
// $in:或查詢,可使用or代替 SQL: SELECT * FROM inventory WHERE status in ("A", "D")
db.inventory.find( { status: { $in: [ "A", "D" ] } } )
// $nin 同$in
邏輯操作符
邏輯操作符涉及的操作如下表所示:
$and 指定查詢同時滿足多個條件查詢子句
$not 指定查詢不滿足條件查詢子句
$nor 指定查詢無法滿足多個條件查詢子句
$or 指定查詢滿足其中某個條件查詢子句
// $and: 邏輯與查詢 SQL: SELECT * FROM inventory WHERE status = "A" AND qty < 30;
db.inventory.find( { $and: [ { status: { $eq: "A" }, qty: { $lt: 30 } } ] } )
// $not: 不符合查詢 SQL: SELECT * FROM inventory WHERE status <> "A";
db.inventory.find( { status: { $not: { $eq: "A" } } } )
/*
$nor: 無法同時滿足多個條件查詢,字段不存在時也符合 SQL: SELECT * FROM inventory WHERE status <> "A" AND qty > 30;
符合以下條件之一都會出現在結果集中:
1.文檔包含status和qty字段并且符合條件;
2.文檔包含status字段并且符合條件,不包含qty字段;
3.文檔不包含status字段,包含qty字段并且符合條件;
4.文檔不包含status字段和qty字段。
*/
db.inventory.find( { $nor: [ { status: { $eq: "A" } }, { qty: { $lt: 30 } } ] } )
// $or: 邏輯或查詢 SQL: SELECT * FROM inventory WHERE status = "A" OR qty < 30;
db.inventory.find( { $or: [ { status: "A" }, { qty: { $lt: 30 } } ] } )
元素操作符
元素操作符主要涉及的操作如下表所示:
$exists 指定查詢文檔是否有對應的字段
$type 指定查詢文檔的某個字段是否是對應類型
// $exists: 是否存在指定字段查詢
db.inventory.find( { price: { $exists: true } } )
// $type: 字段是否是指定類型查詢
db.inventory.find( { "qty": { $type: "double" } } )
評估操作符
評估操作符主要涉及的操作如下表所示,更多操作符可以參考官方文檔:
https://docs.mongodb.com/manual/reference/operator/query-evaluation/。
$expr 為同一個文檔中的字段指定表達式并且符合條件的查詢,比如比較同一文檔當中兩個字段的值
$mod 為字段值取模并且符合條件的查詢
為了更好的使用這兩個主要的操作符,額外建立個文檔:
db.monthlyBudget.insertMany([
{ "_id" : 1, "category" : "food", "budget": 400, "spent": 450 },
{ "_id" : 2, "category" : "drinks", "budget": 100, "spent": 150 },
{ "_id" : 3, "category" : "clothes", "budget": 100, "spent": 50 },
{ "_id" : 4, "category" : "misc", "budget": 500, "spent": 300 },
{ "_id" : 5, "category" : "travel", "budget": 200, "spent": 650 }
// $expr: 允許使用聚合表達式,這裡以$gt為例,更多表達式參考
https://docs.mongodb.com/manual/meta/aggregation-quick-reference/#aggregation-expressionsdb.monthlyBudget.find( { $expr: { $gt: [ "$spent" , "$budget" ] } } )
// $mod: 對字段所在值進行取模運算,顯示符合條件的查詢,如qty字段值對4取模,并且餘數為0
db.inventory.find( { qty: { $mod: [ 4, 0 ] } } )
更新(Update Operations)是對已存在的文檔進行修改操作,MongoDB提供以下幾種主要更新文檔方法:
db.collection.update():更新或替換集合中符合條件的一個或多個文檔;
db.collection.updateOne():隻更新集合中符合條件的第一個文檔,即使有多個文檔(版本3.2新增);
db.collection.updateMany():更新集合中所有符合條件的文檔(版本3.2新增)。
根據update指定的表達式可以修改文檔中符合條件的字段或代替整個文檔。具體的文法格式如下:
db.collection.update(
, //查詢表達式
, //更新表達式
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ],
hint: <document|string> // 版本4.2新增
query:更新文檔的查詢表達式;如果指定了參數upsert: true并且集合中沒有符合查詢條件的文檔,查詢條件中有關于字段_id指定了.分隔符的,并不會插入新的文檔;
update:主要包含三種格式
1.更新文檔:隻包含更新操作符表達式;
2.替換文檔:隻包含: 對;
3.聚合管道:版本4.2新增,詳細參考官方文檔。
upsert:當query查詢條件沒符合更新的文檔,就新建立文檔(可選),預設值為false;
multi:是否更新多個符合條件的文檔(可選),預設值為false,隻更新符合條件的第一個文檔;
writeConcern:參考db.collection.insert()相同參數說明;
collation:指定校對規則(可選,版本3.4新增);
arrayFilters:文檔數組更新過濾操作符(可選,版本3.6新增);
詳細參考:
https://docs.mongodb.com/manual/reference/method/db.collection.update/#specify-arrayfilters-for-array-update-operationshint:采用文檔或字元串的形式指定适用于查詢表達式的索引,如果索引不存在則報錯(可選,版本4.2新增)。
使用示例将通過使用兩種場景進行,一是沒有使用參數選項upsert,二是使用參數選項upsert。
不使用選項upsert
// 測試資料
db.books.remove({});
db.books.insertMany([
{
"_id" : 1,
"item" : "TBD",
"stock" : 0,
"info" : { "publisher" : "1111", "pages" : 430 },
"tags" : [ "technology", "computer" ],
"ratings" : [ { "by" : "ijk", "rating" : 4 }, { "by" : "lmn", "rating" : 5 } ],
"reorder" : false
},
"_id" : 2,
"item" : "XYZ123",
"stock" : 15,
"info" : { "publisher" : "5555", "pages" : 150 },
"tags" : [ ],
"ratings" : [ { "by" : "xyz", "rating" : 5 } ],
"reorder" : false
/* 使用選項參數 upsert: true
1、如果查詢表達式找到比對的文檔,則執行更新操作;
2、如果查詢表達式沒有找到比對的文檔,則執行插入操作;
db.books.update(
{ item: "ZZZ135" }, // 查詢表達式
{ // 更新或替換文檔
item: "ZZZ135",
stock: 5,
tags: [ "database" ]
{ upsert: true }
// 1.使用更新操作表達式
/* $set操作符
1、查詢表達式指定需要更新的文檔 _id;
2、$inc操作符: stock的字段值+5;
3、$set操作符: 替換item字段值,替換嵌入文檔info的publisher字段值,替換tags字段值,替換數組ratings的第二個元素值
{ _id: 1 },
$inc: { stock: 5 },
$set: {
item: "ABC123",
"info.publisher": "2222",
tags: [ "software" ],
"ratings.1": { by: "xyz", rating: 3 }
}
更新之後的文檔:
"_id" : 1,
"item" : "ABC123",
"stock" : 5,
"info" : { "publisher" : "2222", "pages" : 430 },
"tags" : [ "software" ],
"ratings" : [ { "by" : "ijk", "rating" : 4 }, { "by" : "xyz", "rating" : 3 } ],
"reorder" : false
// 2.為已存在的數組添加元素
// $push操作符: 為指定文檔數組ratings添加一個元素
{ _id: 2 },
$push: { ratings: { "by" : "jkl", "rating" : 2 } }
"_id" : 2,
"item" : "XYZ123",
"stock" : 15,
"info" : {
"publisher" : "5555",
"pages" : 150
},
"tags" : [ ],
"ratings" : [
{ "by" : "xyz", "rating" : 5 },
{ "by" : "jkl", "rating" : 2 }
}
// 3.文檔移除字段
// $unset操作符: 移除文檔的指定字段,為_id:1文檔移除tags字段
db.books.update( { _id: 1 }, { $unset: { tags: 1 } } );
更新後的文檔:
"_id" : 1,
"item" : "TBD",
"stock" : 0,
"publisher" : "1111",
"pages" : 430
"ratings" : [ { "by" : "ijk", "rating" : 4 }, { "by" : "lmn", "rating" : 5 } ],
// 4.替換整個文檔
// 替換_id:2的文檔
item: "XYZ123",
stock: 10,
info: { publisher: "2255", pages: 150 },
tags: [ "baking", "cooking" ]
"_id" : 2,
"item" : "XYZ123",
"stock" : 10,
"info" : { "publisher" : "2255", "pages" : 150 },
"tags" : [ "baking", "cooking" ]
// 5.更新多個文檔
{ stock: { $lte: 10 } },
{ $set: { reorder: true } },
{ multi: true }
更新後的全部文檔:
[
"_id" : 1,
"item" : "ABC123",
"stock" : 5,
"info" : {
"publisher" : "2222",
"pages" : 430
},
"ratings" : [ { "by" : "ijk", "rating" : 4 }, { "by" : "xyz", "rating" : 3 } ],
"reorder" : true
"_id" : 2,
"item" : "XYZ123",
"stock" : 10,
"info" : { "publisher" : "2255", "pages" : 150 },
"tags" : [ "baking", "cooking" ],
"reorder" : true
使用upserts選項
// 1.插入未符合更新條件的文檔
{ item: "ZZZ135" },
item: "ZZZ135",
stock: 5,
tags: [ "database" ]
{ upsert: true }
因為集合并未滿足條件的文檔,則插入的文檔為:
"_id" : ObjectId("5da78973835b2f1c75347a83"),
"item" : "ZZZ135",
"tags" : [ "database" ]
// 2.插入未符合更新條件并且基于更新操作符的文檔
// 如果沒有符合更新查詢條件,并且使用的是更新操作符,則會基于目前的查詢條件和更新操作符字段插入新的文檔
{ item: "BLP921" },
$set: { reorder: false },
$setOnInsert: { stock: 10 }
{ upsert: true }
新插入的文檔為:
"_id" : ObjectId("5da79019835b2f1c75348a0a"),
"item" : "BLP921",
"reorder" : false,
"stock" : 10
// 3.插入未符合更新條件并且基于聚合管道的文檔
// 關于聚合管道請參考官方文檔:
https://docs.mongodb.com/manual/reference/method/db.collection.update/#update-with-aggregation-pipeline// 4.插入未符合更新條件并且同時聯合多文檔操作符的文檔
如果不符合查詢條件,則隻會插入單個文檔
{ "info.publisher": "Self-Published" },
$set: { reorder: false, tags: [ "literature", "hardcover" ], stock: 25 }
{ upsert: true, multi: true }
新插入的文檔:
"_id" : ObjectId("5db337934f670d584b6ca8e0"),
"info" : { "publisher" : "Self-Published" },
"stock" : 25,
"tags" : [ "literature", "hardcover" ]
根據update指定的參數可以修改文檔中符合條件的字段或代替整個文檔,與db.collection.update()不同的是每次隻更新單個文檔。
db.collection.updateOne(
upsert: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ],
hint: <document|string>
參考db.collection.update()的參數說明。
// 參考db.collection.update()
根據update指定的參數可以修改文檔中符合條件的字段或代替整個文檔,與db.collection.updateOne()不同的是更新所有符合條件的文檔。
db.collection.updateMany(
upsert: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ],
hint: <document|string>
删除是指對集合當中已存在的文檔進行清除操作,MongoDB提供以下幾種主要删除文檔方法:
db.collection.deleteOne():隻删除集合中符合條件的一個文檔;
db.collection.deleteMany():删除集合中所有符合條件的文檔;
db.collection.remove():删除集合中符合條件的一個或多個文檔。
根據filter選項條件删除集合中的單個文檔,具體文法格式如下:
db.collection.deleteOne(
writeConcern: <document>,
collation: <document>
filter:指定基于查詢表達式的過濾條件,關于查詢表達式可以檢視db.collecion.find()中的;
// 删除指定條件的單個文檔
db.orders.deleteOne( { "_id" : 1 } );
{ "acknowledged" : true, "deletedCount" : 1 }
db.collection.deleteMany(
writeConcern: <document>,
collation: <document>
參考db.collection.deleteOne()的參數說明。
// 删除指定條件的多個文檔
db.orders.deleteMany( {"cust_id" : "Cam Elot"} );
{ "acknowledged" : true, "deletedCount" : 2 }
注意: 如果是對固定集合進行删除文檔操作則會報錯,固定集合的清除操作使用方法db.collection.drop()。
本文簡單梳理了在Mongo Shell下基本的CRUD操作,主要适用于DBA的運維管理,如果是研發同學,根據不同的程式設計語言使用不同用戶端驅動進行操作,詳細同樣可以參考官方文檔;
針對CRUD各個方面還有其他一些額外的方法,比如查詢修改文檔方法db.collection.findAndModify(),這裡隻是總結每個文檔操作中一些最基礎的方法,對于額外進階的方法這裡不再贅述;
掌握了這些基本的CRUD操作,就可以對MongoDB文檔進行操作了,但還是需要控制好權限,畢竟資料安全不是小事,做變更之前做好資料的備份,以防萬一。
☆〖本人水準有限,文中如有錯誤還請留言批評指正!〗☆
作者: H_Johnny
出處:
http://www.cnblogs.com/dbabd/