# MongoDB 基础
# 参考文档
# 安装
// TODO
# 连接
使用连接字符串方式:
mongo "mongodb://host:port"
mongo "mongodb://user:pwd@host:port/db_name?authSource=admin...(即 options)"
# BSON
- binary json。
- BSON 文档的最大大小为 16 MB。
# ObjectId
ObjectId 很小,可能唯一,可以快速生成并排序。ObjectId 值的长度为 12 个字节,包括:
- 一个 4 字节的_时间戳记值_,代表自 Unix 时代以来以秒为单位的 ObjectId 的创建。
- 5 字节_随机值_。
- 3 字节_递增计数器_,初始化为随机值。
在 mongoshell 中,可以使用 ObjectId.getTimestamp()
方法访问 ObjectId 的创建时间。
在存储 ObjectId 值的 _id
字段上按大致相当于创建时间进行排序。
重要: 尽管 ObjectId 值应随时间增加,但不一定是单调的。这是因为他们仅包含一秒的时间分辨率,因此在同一秒内创建的 ObjectId 值没有保证的顺序,并且由客户端生成,客户端可能具有不同的系统时钟。
# 字符串
BSON 字符串为 UTF-8
。通常,在对 BSON 进行序列化和反序列化时,每种编程语言的驱动程序都会从该语言的字符串格式转换为 UTF-8
。这样就可以轻松地将大多数国际字符存储在 BSON 字符串中。
此外,MongoDB $regex
查询在正则表达式字符串中支持 UTF-8
。
# 日期 Date
BSON Date 是一个 64 位整数,代表自 Unix 纪元(1970年1月1日)以来的毫秒数。这导致可以追溯到过去和未来约 2.9 亿年的日期范围。
官方 BSON 规范指的是 BSON Date 类型为 UTC日期时间
。
BSON 日期类型是有符号整数。负值表示 1970 年之前的日期。
示例:
- 在 mongo shell 中使用构造函数
new Date()
构造一个 Date :var mydate1 = new Date()
。 - 在 mongo shell 中使用构造函数
ISODate()
构造一个 Date :var mydate2 = ISODate()
。 - 以字符串形式返回 Date 值:
mydate1.toString()
。 - 返回日期值的月份部分,月是零索引,因此一月是 0 月:
mydate1.getMonth()
。
# 库操作
db
,查看当前数据库。show dbs
use db_name
db.dropDatabase()
,删除当前使用的数据库。
MongoDB 中直接创建一条数据,如果对应的表不存在就会被创建出来。
比如:db.user.insertOne({name:"xiaoming"})
,该命令会同步创建 user 集合(表),如果之前不存在的话。use Haha
,就会将 Haha 库创建出来。
# 集合操作
- 显示所有集合,
show collections
- 创建集合,
db.createCollection('collection',[options])
- 删除集合,
db.collection.drop()
# 文档操作
db.collection.action()
:
find(query, projection).pretty()
,- 默认返回 20 条数据。
- 返回值是一个 cursor。
query
是查询条件,projection
控制字段的显示和隐藏。pretty
是格式化。sort
,1 正序, -1 倒序。skip
,跳过几个。limit
,控制返回条数。
insert(params)
,params
可以是对象,也可以是数组类型。remove(query)
,query
是查询条件。update(query, update, [options])
$set
、$inc
、$pull
、$push
。
# 插入文档
如果该集合当前不存在,则插入操作将创建该集合。
db.collection.insert(one or more)
,一个 or 多个对象数组。db.collection.insertOne({})
,一个对象。db.collection.insertMany([{},{}])
,对象数组。
另外:
db.collection.save()
,如果包含_id
,执行 update,如果不包含,则执行创建。- ...
# 查询文档
db.collection.find()
,返回游标 <==>SELECT * FROM tb
。db.collection.findOne()
,返回文档。
# 查询操作符
$or
$and
$not
$nor
,值是一个数组类型。$eq
、$gt
、$gte
、$in
、$lt
、$lte
、$ne
、$nin
,regex
。$elemMatch
,匹配对象数组。
# $in
查找集合中 status = A 或 D 的所有文档:
db.collection.find( { status: { $in: [ "A", "D" ] } } )
<==> SELECT * FROM tb WHERE status in ("A", "D")
# $and
查找集合中 status = A 并且 qty <($lt) 30 的所有文档:
db.collection.find( { status: "A", qty: { $lt: 30 } } )
<==> SELECT * FROM tb WHERE status = "A" AND qty < 30
# $or
查找集合中 status = A 或者 qty <($lt) 30 的所有文档:
db.collection.find({
$or: [
{ status: "A" },
{ qty: { $lt: 30 } }
]
})
// <==> SELECT * FROM db WHERE status = "A" OR qty < 30
// And 操作与 Or 操作一样,也可以写成 $and:[{..},{..},...] 的形式,但可省略。
2
3
4
5
6
7
8
# 控制返回字段/projection
_id 默认返回,除_id 字段外,不能在映射文档中同时使用包含和去除语句!!!
# 所有字段
如果没有指定 projection
,find()
会返回文档的所有字段。
db.collection.find( { status: "A" } )
<==> SELECT * from tb WHERE status = "A"
# 仅返回指定字段和_id字段
db.collection.find( { status: "A" }, { item: 1, status: 1 } )
<==> SELECT _id, item, status from tb WHERE status = "A"
# 去除_id字段
db.collection.find( { status: "A" }, { item: 1, status: 1, _id: 0 } )
<==> SELECT item, status from tb WHERE status = "A"
# 去除指定字段
除 _id 字段外,不能在映射文档中同时使用包含和去除语句。
db.collection.find( { status: "A" }, { status: 0, instock: 0 } )
# 查询空字段或缺少字段
使用 $exist
查询不包含 age 字段的文档:
db.collection.find( { age : { $exists: false } } )
# 数组查询
首先造一些实验数据:
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 ] }
]);
2
3
4
5
6
7
# 单条件
查询数组字段 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,或者一个元素满足 >15,另外一个元素 <20 的所有文档:
db.inventory.find( { dim_cm: { $gt: 15, $lt: 20 } } )
全满足: 查询数组字段 dim_cm 中最少一个元素同时满足 >($gt)22 并且 <($lt) 30:
db.inventory.find( { dim_cm: { $elemMatch: { $gt: 22, $lt: 30 } } } )
使用
$elemMatch
来指定多个查询条件在数组中的元素上,数组中最少一个元素同时满足所有的查询条件。
# 使用数组长度来检索
使用 $size
操作符通过数组中的元素个数来进行检索。
查询数组字段 tags 中有三个元素的所有文档: db.inventory.find( { "tags": { $size: 3 } } )
。
# 查询嵌入式对象数组
首先造一些实验数据:
db.inventory.insertMany( [
{ item: "journal", instock: [ { warehouse: "A", qty: 5 }, { warehouse: "C", qty: 15 } ] },
{ item: "notebook", instock: [ { warehouse: "C", qty: 5 } ] },
{ item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 15 } ] },
{ item: "planner", instock: [ { warehouse: "A", qty: 40 }, { warehouse: "B", qty: 5 } ] },
{ item: "postcard", instock: [ { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ] }
]);
2
3
4
5
6
7
查询 instock 数组中元素等于指定文档的的所有文档:
正确的是:
db.inventory.find( { "instock": { warehouse: "A", qty: 5 } } )
。当对整个嵌套文档使用等值匹配的时候是要求精确匹配指定文档,包括字段顺序。比如,下面的语句并没有查询到 inventory 集合中的任何文档:
db.inventory.find( { "instock": { qty: 5, warehouse: "A" } } )
。查询 instock 数组中的第一个元素是包含字段 qty <= 20 的所有文档:
db.inventory.find( { 'instock.0.qty': { $lte: 20 } } )
注意: 当查询使用点号
.
的时候,字段和索引必须在引号内。使用
$elemMatch
操作符为数组中的嵌套文档指定多个查询条件,最少一个嵌套文档同时满足所有的查询条件。
# 更新文档
更新方法定义:
db.collection.update(
<query>,
<update>,
{
// 可选。如果设置为 true,则在没有文档符合查询条件时创建一个新文档。默认值为 false。
upsert: <boolean>,
// 可选。如果设置为 true,则更新满足 query 条件的多个文档。如果设置为false,则更新一个文档。默认值为false。
multi: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ],
hint: <document|string> // Available starting in MongoDB 4.2
}
)
2
3
4
5
6
7
8
9
10
11
12
13
14
主要方法有:
db.collection.update()
db.collection.updateOne()
db.collection.updateMany()
db.collection.replaceOne()
附加方法:
db.collection.save()
db.collection.findAndModify()
db.collection.findOneAndUpdate()
db.collection.findOneAndReplace()
db.collection.bulkWrite()
# 更新操作符
$set
、$unset
移除字段、$inc
、$pull
、$push
。
不加操作符,就是全量替换。
示例:
将 _id=15 的用户 name 修改为 xiaoming:
db.user.updateOne( { _id: 15 }, { $set: { "name": "xiaoming"} })
# 删除文档
db.collection.deleteOne()
db.collection.deleteMany()
# 游标
在 mongo shell 脚本中打印结果游标中的所有项目,请使用以下惯用法:
cursor = db.collection.find();
while ( cursor.hasNext() ) {
printjson( cursor.next() );
}
2
3
4
也可以使用游标方法 forEach()
来迭代游标并访问文档,如下例所示:
var myCursor = db.users.find( { type: 2 } );
myCursor.forEach(printjson);
2
# 讨论区
由于评论过多会影响页面最下方的导航,故将评论区做默认折叠处理。
点击查看评论区内容,渴望您的宝贵建议~
← MongoDB 目录 MongoDB 高级 →