MongoDB是一款开源的、分布式文档型数据库产品,其提供了无结构、高性能、高可用、自动伸缩的特性吸引了不少开发者的青睐,公司里面不少项目中都有它的影子,所以打算学习学习。
MongoDB Docker仓库地址bitnami/mongodb,本文中所有命令都在mongo shell环境下执行
基本概念
MongoDB | 关系型数据库 |
---|---|
db | database |
collection | table |
document | row |
上述表中的概念并不是严格对等,在MongoDB中不需要事先创建db或collection,插入文档时不存在对应的db或collection会自动创建
一条数据记录在MongoDB中定义为一个文档,内部以BSON作为其存储格式,BSON基本格式与JSON类似:
切换到test数据库:
use test
查看数据库中的集合:
show collections
查看当前MongoDB实例中存在的数据库:
show databases
当前使用的是哪个数据库:
db.getName()
mongo shell中查看对象支持的方法,都可以通过名称.help()查看:
db.help()
CRUD
插入
MongoDB插入支持单条、批量插入,基本使用方式:
> use test
> db.inventory.insertOne({ item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } })
{
"acknowledged" : true,
"insertedId" : ObjectId("5c0a382808d4278148c007e1")
}
> db.inventory.insertMany([
... { item: "journal", qty: 25, tags: ["blank", "red"], size: { h: 14, w: 21, uom: "cm" } },
... { item: "mat", qty: 85, tags: ["gray"], size: { h: 27.9, w: 35.5, uom: "cm" } },
... { item: "mousepad", qty: 25, tags: ["gel", "blue"], size: { h: 19, w: 22.85, uom: "cm" } }
... ])
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5c0a382d08d4278148c007e2"),
ObjectId("5c0a382d08d4278148c007e3"),
ObjectId("5c0a382d08d4278148c007e4")
]
}
MongoDB默认会自动为每条文档生成一个ObjectID对象作为其唯一标识
查询
测试数据集:
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.inventory.find()
等价于SQL:
SELECT * FROM inventory
等值查询:
db.inventory.find( { status: "D" } )
等价SQL:
SELECT * FROM inventory WHERE status = "D"
MongoDB查询选择器支持如下比较操作符:
Name | Description |
---|---|
$eq | Matches values that are equal to a specified value. |
$ne | Matches all values that are not equal to a specified value. |
$gt | Matches values that are greater than a specified value. |
$gte | Matches values that are greater than or equal to a specified value. |
$lt | Matches values that are less than a specified value. |
$lte | Matches values that are less than or equal to a specified value. |
$in | Matches any of the values specified in an array. |
$nin | Matches none of the values specified in an array. |
比较操作符的语法格式为:
{ <field1>: { <operator1>: <value1> }, ... }
比如查询qty大于等于50的文档:
db.inventory.find({qty: {$gte: 50}})
其他比较操作符与此类似,不做过多叙述
MongoDB支持四个逻辑运算符:
Name | Description |
---|---|
$and | Joins query clauses with a logical AND returns all documents that match the conditions of both clauses. |
$not | Inverts the effect of a query expression and returns documents that do not match the query expression. |
$nor | Joins query clauses with a logical NOR returns all documents that fail to match both clauses. |
$or | Joins query clauses with a logical OR returns all documents that match the conditions of either clause. |
一些使用例子:
db.inventory.find( { status: "A", qty: { $lt: 30 } } )
等价SQL:
SELECT * FROM inventory WHERE status = "A" AND qty < 30
db.inventory.find( { $or: [ { status: "A" }, { qty: { $lt: 30 } } ] } )
等价SQL:
SELECT * FROM inventory WHERE status = "A" OR qty < 30
db.inventory.find({qty: {$not: {$gt: 40}}})
等价SQL:
SELECT * FROM inventory WHERE NOT qty > 40
db.inventory.find({$nor: [{qty: 25}, {status: "D"}, {"item": "note"}]})
等价SQL:
SELECT * FROM inventory WHERE NOT qty = 25 and not status = "D" and not item = "note"
find函数支持两个参数,上面查询例子中仅使用了query参数,其第二个参数为projection,主要作用用于明确指定返回的字段,从而降低网络传输,基本语法:
{ field1: <value>, field2: <value> ... }
value取值为0、1、true、false、Projection Operators,例如指定返回文档仅包含item字段(_id默认返回):
db.inventory.find({}, {item: 1})
更多关于MongoDB查询说明,可参考官方文档提供的例子Query Documents
更新
MongoDB同样地支持单条、批量更新,不过MongoDB需要特定的更新操作符来完成更新,这里罗列比较常用的一些更新操作符:
Name | Description |
---|---|
$currentDate | Sets the value of a field to current date, either as a Date or a Timestamp. |
$inc | Increments the value of the field by the specified amount. |
$min | Only updates the field if the specified value is less than the existing field value. |
$max | Only updates the field if the specified value is greater than the existing field value. |
$mul | Multiplies the value of the field by the specified amount. |
$rename | Renames a field. |
$set | Sets the value of a field in a document. |
$unset | Removes the specified field from a document. |
更新使用例子:
db.inventory.updateOne({}, {$inc: {qty: 1}})
等价SQL:
UPDATE inventory SET qty = qty + 1 LIMIT 1
db.inventory.updateMany({status: "A"}, {$set: {status: "H"}})
等价SQL:
UPDATE inventory SET status = "H" where status = "A"
上述例子中MongoDB的更新与其对应的SQL并不完全对等,这里只是简要说明更新操作符的语义。
在MongoDB中,由于schema-less特性,更新数据时可能会导致一些 DDL语义,比如新增字段;另外,MongoDB的DDL和DML是混在一起的
删除
删除数据比较简单,两个简单例子:
db.inventory.deleteMany({ status : "A" })
db.inventory.deleteOne( { status: "D" } )
关于MongoDB的删除,有个地方需要注意:删除记录不释放磁盘空间,这很容易理解,为避免记录删除后的数据大规模挪动,原记录空间不删除,只标记“已删除”即可,以后还可以重复利用,可通过db.repairDatabase()来整理,但这个过程比较缓慢
索引
MongoDB索引使用B树,创建索引基本语法:
db.collection.createIndex(keys, options)
keys参数为一个健值对对象,健为索引字段,值为索引字段类型,1为升序,-1为降序;options参数可用于指定索引名称、是否唯一、存储引擎等
在inventory集合中给qty加上索引:
db.inventory.createIndex({qty: 1}, {name: "idx_inventory_qty"})
查看inventory集合中存在的索引:
db.inventory.getIndexes()
删除inventory集合中qty字段索引:
db.inventory.dropIndex({qty: 1})
查看inventory集合中索引占用内存空间的大小,单位为字节:
db.inventory.totalIndexSize()
inventory集合中创建(qty, status)联合唯一索引:
db.inventory.createIndex({qty: 1, status: -1}, {unique: true})
MongoDB支持多种类型索引,比如稀疏索引、哈希索引、TTL索引、全文索引等,暂时还没有用到这么多,就不做过多介绍,更多的索引说明可参见官方文档Indexesrr