01. 数据类型与操作
MongoDB 基础
一、数据类型
1.1 BSON
文档
Type (类型) | Alias (别名) | Notes (注释) |
---|---|---|
Double | “double” | 双精度型 |
String | “string” | 字符串类型,默认的编码类型为 |
Object | “object” | 对象类型 |
Array | “array” | 数据类型 |
Binary data | “binData” | 二进制数据 |
Undefined | “undefined” | 该数据类型已经废弃 |
ObjectId | “objectId” | 对象 |
Boolean | “bool” | 布尔值 |
Date | “date” | 日期类型 |
Null | “null” | 空 |
Regular Expression | “regex” | 正则表达式 |
DBPointer | “dbPointer” | 该数据类型已经废弃 |
JavaScript | “javascript” | |
Symbol | “symbol” | 该数据类型已经废弃 |
JavaScript (with scope) | “javascriptWithScope” | |
32-bit integer | “int” | |
Timestamp | “timestamp” | 时间戳类型 |
64-bit integer | “long” | |
Decimal128 | “decimal” | 用于解决浮点型丢失精度的问题 |
Min key | “minKey” | |
Max key | “maxKey” |
1.2 ObjectId
在上面的表格中有一个比较重要的数据类型是:ObjectId 。存储在_id
字段作为主键,可以在插入的时候手动指定,或者由程序自动生成,这个字段可以是任何的数据类型,默认是
-
前
4 个字节是从标准纪元开始的时间戳,单位为秒; -
中
5 个字节是由两个部分组成:前3 个字节是所在主机的唯一标识,通常是主机名的散列值,用于保证不同主机生成不同ObjectId ,后两个字节是进程标识符(PID) ,用于保证同一主机上不同进程产生不同的ObjectId 。 -
最后
3 个字节是一个自动增加的计数器,确保相同主机上相同进程在同一秒产生的ObjectId 也是不同的,即每个进程一秒最多可以拥有16777216 个不同的ObjectId (16777216 = (2**8)**3 ,1 个字节等于8 位二进制) 。
二、新增数据
db.collection.insert()
在
db.collection.insertOne()
db.collection.insertMany()
新增单条数据的示例如下。额外需要说明的是,在插入文档前,文档所属的集合不必预先创建,程序会自动创建:
db.user.insertOne({
name: "heibai",
age: 26,
birthday: new Date(1998,08,23),
createTime: new Timestamp(),
Hobby: ["basketball", "football", "tennis"]
})
新增多条数据的示例如下:
db.user.insertMany([
{
name: "hei",
age: 32,
birthday: new Date(1989,08,23),
createTime: new Timestamp(),
Hobby: ["basketball", "football", "tennis"]
},
{
name: "ying",
age: 46,
birthday: new Date(1978,08,23),
createTime: new Timestamp(),
Hobby: ["basketball", "football", "tennis"]
}
])
# 此时会返回新插入的数据的ObjectId
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5d3d0489ad38cd3becc7b03b"),
ObjectId("5d3d0489ad38cd3becc7b03c")
]
}
三、查询数据
3.1 基本API
查询数据的基本语法如下:
db.collection.find(<query>, <projection>)
<query>
:用于指定查询条件,不加任何条件则默认查询集合中全部数据;<projection>
:可选操作,用于过滤返回字段,1 表示对应的字段包含在返回结果中,0 表示不包含,示例如下:
db.user.find({},{name: 1, ObjectId:-1})}
3.2 等值查询
想要查询某个字段等于指定值的数据,可以使用如下语法:
db.user.find({name:"heibai"})
上面的语法实际上是 $eq
操作的简写形式,如下:
db.user.find({name: {$eq: "heibai"}})
所以如果你想要进行非等值查询,则可以使用 $ne
操作符,代表
db.user.find({name: {$ne: "heibai"}})
特别的,如果你想允许某个字段等于多个值,可以使用 $in
操作符,示例如下:
db.user.find({name: {$in:["heibai","ying"]} })
3.3 范围查询
$lt
、$lte
、$gt
和 $gte
,分别对应
db.user.find({age: {$gt: 20, $lt: 40}})
3.4 逻辑查询
$or
、$and
、$not
、$nor
,用于处理多个条件间的逻辑关系,示例如下:
查询姓名为
db.user.find( { $or: [{ name: "heibai" }, { age: { $gt: 30 } }] })
查询姓名不是以
db.user.find({name: {$not: /^hei*/}})
如果要求
db.user.find( { $nor: [{ name: "heibai" }, { age: { $gt: 30 } }] })
3.5 集合查询
如果需要查询个人爱好中有
db.user.find({Hobby: "football"})
如果想要获取集合中指定位置等于指定值的文档,对应的查询语句如下:
db.user.find({"Hobby.2": "football"})
如果想要约束集合必须包含多个指定值,此时可以使用
db.user.find({Hobby:{ $all: ["football", "tennis"]}})
查询时如果只想返回集合的部分内容,则可以使用
db.user.find({name: "heibai"},{Hobby:{$slice: 2}})
3.6 额外操作
在查询操作之后,skip
、sort
和 limit
,分别用于表示跳过一定量的数据、按照指定规则对数据进行排序和限制返回数据的量,示例如下:
db.user.find({})
.skip(1)
.sort({_id:-1})
.limit(10)
四、修改数据
4.1 基本API
db.collection.replaceOne(<filter>, <update>, <options>)
db.collection.updateOne(<filter>, <update>, <options>)
db.collection.updateMany(<filter>, <update>, <options>)
<filter>
:过滤条件,用于查询需要修改的数据;<update>
:更改操作或新文档数据;<options>
:可选操作,常用的可选操作是upsert
,当其为true 时,代表如果按照过滤条件没有找到对应的文档,则将待更改的数据插入到集合中;当其为false 时,如果没有找到数据,则不执行任何操作。示例如下:
db.user.replaceOne(
{ _id: ObjectId("5d3d00a4ad383d3becc7b03a")},
{
name: "danrenying",
age: 32,
birthday: new Date(1995,08,23),
createTime: new Timestamp(),
Hobby: ["basketball", "football", "tennis"]
},
{upsert : true}
)
4.2 常规修改器
想要对数据进行修改,必须明确表达修改行为,在
1. $set
用于修改具体的字段,如果待修改的字段不存在,则会新增该字段。示例如下:
db.user.updateOne(
{ name: "danrenying"},
{ $set: {age: 66} }
)
2. $inc
用于对指定字段的值进行增加或减少,示例如下:
db.user.updateOne(
{ name: "danrenying"},
{ $inc: {age: -10} }
)
4.3 数组修改器
在修改操作中,比较复杂的是对数组数据的修改,为了解决这个问题,
1. $push
用于往数组中新增数据,示例如下。使用 $each
可以一次添加多个元素:
db.user.updateOne(
{ name: "danrenying"},
{ $push: {"Hobby": {$each: ["film","music"]}} }
)
2. $addToSet
该修改器可以把数组当做集
db.user.updateOne(
{ name: "danrenying"},
{ $addToSet: {"Hobby": {$each: ["film","music"]}} }
)
3. $pop
该修改器可以从数组任意一端删除元素,-1
代表从数组头删除元素,1
代表从数组尾删除元素,示例如下:
db.user.updateOne(
{ name: "danrenying"},
{ $pop: {"Hobby": -1} }
)
4. index
用于直接修改指定下标位置的元素,示例如下:
db.user.updateOne(
{ name: "danrenying"},
{ $set: {"Hobby.0": "Cooking"} }
)
五、删除数据
db.collection.deleteMany()
db.collection.deleteOne()
使用示例如下:
db.user.deleteOne(
{ name: "danrenying"}
)
参考资料
-
Kristina Chodorow . MongoDB 权威指南(第2 版). 人民邮件出版社. 2014-01