本文是 MongoDB 新手入门 系列的第一篇,在本文中,咱们将会解说 MongoDB 根本的增删改查操作,在学习完本文后,读者将会把握对 MongoDB 的汇合文档进行根本的新增,批改,删除以及基于多种条件的查问操作。
本文将会继续修改和更新,最新内容请参考我的 GITHUB 上的 程序猿成长打算 我的项目,欢送 Star,更多精彩内容请 follow me。
插入文档
在 MongoDB shell 中,插入文档有以下两个办法:
- 应用
db.collection.insertOne()
插入单个文档 - 应用
db.collection.insertMany()
插入多个文档
在插入文档时,如果 collection 不存在,插入操作将会主动创立 collection。如果文档没有 _id
字段, MongoDB 将会主动增加一个 _id
字段,类型为 ObjectId
。
在 MongoDB 中,每一个文档都须要一个惟一的
_id
字段作为主键,如果插入时没有指定_id
字段,MongoDB 驱动将会主动生成一个类型为ObjectId
的_id
字段。
ObjectId
是一种可能疾速生成的,有序的,12 字节大小的惟一值,蕴含:
- 一个 4 字节的工夫戳,代表了 ObjectId 的创立工夫,取值为 Unix 工夫戳(秒)
- 一个 5 字节的随机值,该值每个过程都只会生成一次,对每台服务器和过程来说该值是惟一的
- 一个 3 字节的自增值,初始为一个随机数
use sample_mflix// 插入单个文档db.movies.insertOne( { title: "The Favourite", genres: [ "Drama", "History" ], runtime: 121, rated: "R", year: 2018, directors: [ "Yorgos Lanthimos" ], cast: [ "Olivia Colman", "Emma Stone", "Rachel Weisz" ], type: "movie" })// 插入多个文档db.movies.insertMany([ { title: "Jurassic World: Fallen Kingdom", genres: [ "Action", "Sci-Fi" ], runtime: 130, rated: "PG-13", year: 2018, directors: [ "J. A. Bayona" ], cast: [ "Chris Pratt", "Bryce Dallas Howard", "Rafe Spall" ], type: "movie" }, { title: "Tag", genres: [ "Comedy", "Action" ], runtime: 105, rated: "R", year: 2018, directors: [ "Jeff Tomsic" ], cast: [ "Annabelle Wallis", "Jeremy Renner", "Jon Hamm" ], type: "movie" }])
除了罕用的 insertOne
和 insertMany
办法之外,还能够用以下形式插入文档
db.collection.bulkWrite()
配合
upsert: true
选项db.collection.updateOne()
db.collection.updateMany()
db.collection.findAndModify()
db.collection.findOneAndUpdate()
查问文档
最根本的查询方法是 db.collection.find()
和 db.collection.findOne()
,在 MongoDB 中插入以下文档
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" }]);
查问 Collection 中所有文档
// 等价 SQL:SELECT * FROM inventorydb.inventory.find({})// 等价 SQL:SELECT * FROM inventory LIMIT 1db.inventory.findOne({})
指定查问条件
等值查问
// 等价 SQL:SELECT * FROM inventory WHERE status = "D"db.inventory.find({status: "D"})// 等价 SQL:SELECT * FROM inventory WHERE status != "D"db.inventory.find({ status: { $ne: "D" } })
IN 查问
// 等价 SQL:SELECT * FROM inventory WHERE status in ("A", "D")db.inventory.find({status: { $in: ["A", "D"]}})// 等价 SQL: SELECT * FROM inventory WHERE status NOT IN ("A", "D")db.inventory.find({ status: { $nin: ["A", "D"] } })
范畴查问
// SQL: SELECT * FROM inventory WHERE qty >= 50 AND qty < 100db.inventory.find({ qty: { $gte: 50, $lt: 100 } })
比拟操作符反对这些: $lt
,$gt
,$gte
,$lte
。
AND 查问
// SQL:SELECT * FROM inventory WHERE status = "A" AND qty < 30db.inventory.find({ status: "A", qty: { $lt: 30 } })
OR 查问
// SQL:SELECT * FROM inventory WHERE status = "A" OR qty < 30db.inventory.find({ $or: [ { status: "A"}, { qty: { $lt: 30 } } ] })
同时应用 AND 和 OR
// SQL: SELECT * FROM inventory WHERE status = "A" AND ( qty < 30 OR item LIKE "p%" )db.inventory.find({ status: "A", $or: [ { qty: { $lt: 30 } }, { item: /^p/ } ]})
NOT
// 查问 qty 模 5 值为 1 的所有文档,这里匹配的 qty 可能值为 1, 6, 11, 16 等db.inventory.find({ qty: { $mod: [5, 1] } })// 查问 qty 模 5 值部位 1 的所有文档,可能值为2, 3, 4, 5, 7, 8, 9, 10, 12 等db.inventory.find({ qty: { $not: { $mod: [5, 1] } } })
查问嵌套的文档
查问所有 size
等于 { h: 14, w: 21, uom: "cm" }
的文档
db.inventory.find( { size: { h: 14, w: 21, uom: "cm" } } )
查问所有 size
中 uom
等于 in
的文档
db.inventory.find( { "size.uom": "in" } )
查问数组
在 MongoDB 中插入以下文档
db.inventory.insertMany([ { item: "journal", qty: 25, tags: ["blank", "red"], dim_cm: [ 14, 21 ] }, { item: "notebook", qty: 50, tags: ["red", "blank"], dim_cm: [ 14, 21 ] }, { item: "paper", qty: 100, tags: ["red", "blank", "plain"], dim_cm: [ 14, 21 ] }, { item: "planner", qty: 75, tags: ["blank", "red"], dim_cm: [ 22.85, 30 ] }, { item: "postcard", qty: 45, tags: ["blue"], dim_cm: [ 10, 15.25 ] }]);
上面的示例查问所有字段 tags
值只蕴含元素 "red" 和 "blank"(程序统一) 的文档
db.inventory.find({ tags: ["red", "blank"]})
如果只是查问同时蕴含 "red" 和 "blank" 两个值,并且不关怀排序或者数组中是否蕴含其它元素,则能够应用 $all
操作符
db.inventory.find({ tags: { $all: ["red", "blank"] } })
查问 tags
蕴含 "red" 的文档
db.inventory.find({ tags: "red" })
查问所有 dim_cm
蕴含至多一个大于值 25 的所有文档
db.inventory.find({ dim_cm: { $gt: 25} })
查问所有 dim_cm
蕴含至多一个值大于 15 或者 小于 20 的所有文档
db.inventory.find({ dim_cm: { $gt: 15, $lt: 20 } })
查问所有 dim_cm
蕴含至多一个值大于 22 且小于 30 的所有文档
db.inventory.find({ dim_cm: { $elemMatch: { $gt: 22, $lt: 30} } })
查问数组 dim_cm
的第二个值大于 25
db.inventory.find({ "dim_cm.1": { $gt: 25 }})
查问数组 tags
领有 3 个元素的所有文档
db.inventory.find({ "tags": { $size: 3 } })
查问返回指定字段
默认状况下,MongoDB 的查问会返回匹配文档中所有的字段,通过 projection
能够返回指定的字段。
返回指定字段
// SQL: SELECT _id, item, status FROM inventory WHERE status = "A"db.inventory.find({ status: "A" }, { item: 1, status: 1 })
查问后果中会主动返回 _id
字段,能够通过设置 _id: 0
来被动打消该字段。
// SQL: SELECT item, status FROM inventory WHRE status = "A"db.inventory.find( { status: "A" }, { item: 1, status: 1, _id: 0 } )
排除指定字段
db.inventory.find({ status: "A" }, { status: 0, instock: 0 })
返回数组中指定元素
应用 $slice
操作符返回 instock
数组中最初一个元素
db.inventory.find({ status: "A" }, { item: 1, status: 1, instock: { $slice: -1 } })
查问值为 NULL 或者缺失字段
在 MongoDB 中,不同的查问操作符对 null
的解决形式是不同的。在 MongoDB 中插入以下文档
db.inventory.insertMany([ { _id: 1, item: null }, { _id: 2 }])
等值查问
查问 item
值为 null
或者不蕴含 item
字段的所有文档
db.inventory.find({ item: null })
类型查看
查问所有 item
值为 null
的文档
db.inventory.find({ item: { $type: 10} })
这里的$type = 10
对应了 BSON 类型Null
存在性查看
查问所有不蕴含字段 item
的文档
db.inventory.find({ item: { $exists: false } })
查问所有蕴含 item 字段,然而值为 null
的文档
db.inventory.find({ item: { $eq: null, $exists: true } })
限度查问后果数量
// 只查问 3 条数据db.inventory.find({}).limit(3)// 从第 2 条开始,查问 3 条数据db.inventory.find({}).limit(3).skip(2)
排序
排序方向 1
为正序, -1
为倒序。
db.inventory.find({}).sort({item: 1, qty: -1})
查问汇合中的文档数量
该办法用于查问匹配条件的文档数量,语法为
db.collection.count(query, options)
示例
db.orders.count( { ord_dt: { $gt: new Date('01/01/2012') } } )
查问字段的惟一值 distinct
查问汇合中字段的惟一值,语法为
db.collection.distinct(field, query, options)
附录:反对的查问操作符
类别 | 操作符 | 用处 |
---|---|---|
Comparison | $eq | 等值判断 |
Comparison | $gt | 大于某个值 |
Comparison | $gte | 大于等于某个值 |
Comparison | $in | 以后值在数组中 |
Comparison | $lt | 小于某个值 |
Comparison | $lte | 小于等于某个值 |
Comparison | $ne | 不等于某个值 |
Comparison | $nin | 以后值不再数组中 |
Logical | $and | AND |
Logical | $not | 反转查问条件 |
Logical | $nor | 所有查问条件都不匹配 |
Logical | $or | OR |
Element | $exists | 字段存在性查看 |
Element | $type | 字段类型查看 |
Evaluation | $expr | 在查问表达式中应用聚合语法 |
Evaluation | $jsonSchema | 验证文档合乎指定的 JSON 模型 |
Evaluation | $mod | 对字段值进行取模运算 |
Evaluation | $regex | 抉择匹配正则表达式的文档 |
Evaluation | $text | 执行文本搜寻 |
Evaluation | $where | JavaScript 表达式匹配 |
Geospatial | $geoIntersects | 地理坐标匹配 |
Geospatial | $geoWithin | 地理坐标匹配 |
Geospatial | $near | 地理坐标匹配 |
Geospatial | $nearSphere | 地理坐标匹配 |
Array | $all | 匹配蕴含查问中指定的所有元素的数组 |
Array | $elemMatch | 数组中的元素匹配表达式则返回文档 |
Array | $size | 抉择数组大小为 size 的文档 |
Bitwise | $bitsAllClear | 二进制匹配 |
Bitwise | $bitsAllSet | 二进制匹配 |
Bitwise | $bitsAnyClear | 二进制匹配 |
Bitwise | $bitsAnySet | 二进制匹配 |
Miscellaneous | $comment | 在查问中增加正文 |
Miscellaneous | $rand | 随机生成一个 0-1 之间的浮点值 |
更新文档
罕用的文档更新办法有以下三种
db.collection.updateOne(<filter>, <update>, <options>)
更新单个文档db.collection.updateMany(<filter>, <update>, <options>)
更新多个文档db.collection.replaceOne(<filter>, <update>, <options>)
替换单个文档
咱们这里以 updateOne()
办法为例进行解说,updateOne()
办法的语法如下
db.collection.updateOne( <filter>, // 要更新的文档筛选条件 <update>, // 文档更新命令 { upsert: <boolean>, // 设置为 true 时,如果 filter 没有匹配到文档,则主动新增文档 writeConcern: <document>, collation: <document>, arrayFilters: [ <filterdocument1>, ... ], hint: <document|string> // Available starting in MongoDB 4.2.1 })
更新 item=paper
的文档
db.inventory.updateOne( { item: "paper" }, { $set: { "size.uom": "cm", status: "P" }, $currentDate: { lastModified: true } })
更新操作符如下
$set
操作符指定了要更新匹配文档的size.uom
为cm
,status
为p
$currentDate
操作符用于更新lastModified
字段为以后的日期,如果lastModified
字段不存在,则主动创立
更新文档,如果不存在则新增
db.restaurant.updateOne( { "name" : "Pizza Rat's Pizzaria" }, { $set: {"_id" : 4, "violations" : 7, "borough" : "Manhattan" } }, { upsert: true });
更多字段操作符如下
操作符 | 用处 |
---|---|
$currentDate | 设置字段值为当日期,能够是日期或者是工夫戳 |
$inc | 将字段的值加上某个数值 |
$min | 只有指定的值小于曾经存在的值时才更新 |
$max | 只有指定的额值大于曾经存在的值才更新 |
$mul | 将字段的值乘以某个数值 |
$rename | 重命名指定字段 |
$set | 设置文档中要更新的字段值 |
$setOnInsert | 如果以后操作新增了文档,则设置字段的值。如果更新操作只是批改一个曾经存在的文档,则该操作符有效 |
$unset | 从文档中移除指定字段 |
除了罕用的三个办法,还有以下办法也能够用于更新文档
db.collection.findOneAndReplace()
.db.collection.findOneAndUpdate()
.db.collection.findAndModify()
.db.collection.bulkWrite()
.
删除文档
在 MongoDB 中,通常应用以下办法删除文档
db.collection.deleteMany()
db.collection.deleteOne()
删除所有为文档
db.inventory.deleteMany({})
删除所有匹配条件的文档
db.inventory.deleteMany({ status : "A" })
删除匹配条件的一个文档
db.inventory.deleteOne( { status: "D" } )
除了罕用的两个办法外,还能够用以下办法删除文档
db.collection.findOneAndDelete()
.findOneAndDelete() 提供了一个
sort
选项,该选项容许删除依照指定排序规定排序后匹配的第一个文档db.collection.findAndModify()
.db.collection.findAndModify()
提供了一个sort
选项,该选项容许删除依照指定排序规定排序后匹配的第一个文档db.collection.bulkWrite()
.
批量写操作
MongoDB 提供了一种对单个 Collection 执行批量写入的操作能力,应用 db.collection.bulkWrite()
办法实现批量的插入、更新和删除操作。
有序和无序操作
批量写操作能够试有序的(ordered
)或者无序(unordered
)的,对于有序操作,MongoDB 会串行的执行操作,如果写操作过程中产生谬误,MongoDB 将会间接返回,前面的操作将不会被执行。无序操作则无奈保障这种行为,当产生谬误的时候,MongoDB 将会持续解决残余的文档。
对于分片的汇合来说,执行有序的批量操作通常会比较慢,因为每一个操作都必须期待上一个操作的实现。默认状况下,bulkWrite()
执行的是有序的操作,能够通过设置 ordered: false
选项来启用无序操作模式。
bulkWrite() 办法
bulkWrite()
反对以下写操作
- insertOne
- updateOne
- updateMany
- replaceOne
- deleteOne
- deleteMany
假如一个名为 characters
的汇合中蕴含上面的文档
{ "_id" : 1, "char" : "Brisbane", "class" : "monk", "lvl" : 4 },{ "_id" : 2, "char" : "Eldon", "class" : "alchemist", "lvl" : 3 },{ "_id" : 3, "char" : "Meldane", "class" : "ranger", "lvl" : 3 }
上面的 bulkWrite()
办法对该汇合执行多个操作
db.characters.bulkWrite( [ { insertOne : { "document" : { "_id" : 4, "char" : "Dithras", "class" : "barbarian", "lvl" : 4 } } }, { insertOne : { "document" : { "_id" : 5, "char" : "Taeln", "class" : "fighter", "lvl" : 3 } } }, { updateOne : { "filter" : { "char" : "Eldon" }, "update" : { $set : { "status" : "Critical Injury" } } } }, { deleteOne : { "filter" : { "char" : "Brisbane" } } }, { replaceOne : { "filter" : { "char" : "Meldane" }, "replacement" : { "char" : "Tanys", "class" : "oracle", "lvl" : 4 } } } ]);
操作返回以下内容
{ "acknowledged" : true, "deletedCount" : 1, "insertedCount" : 2, "matchedCount" : 2, "upsertedCount" : 0, "insertedIds" : { "0" : 4, "1" : 5 }, "upsertedIds" : { }}
参考文档
- MongoDB 官网文档