MongoDB

MongoDB#

本文非常长,共计12200词,请注意阅读时间,撰写四天时间,原创不易,转载请注明。

一、概述#

1.数据#

能够输入到计算机中并被识别处理的信息集合

2. 数据结构#

研究一个数据集合中,数据元素关系

3. 数据库#

按照数据结构,存储管理数据的仓库,数据仓库是在数据库管理系统控制下在一定介质中创建的

4.数据库管理系统#

数据库管理软件

5.数据库系统#

由数据库和数据库管理系统等构成的数据开发工具集合

二、 关系与非关系#

1. 关系型数据库#

采用关系模型(二维表)来组织数据结构的数据库

Oracle、DB2、SQLServer、MySQL、SQLite

优点

  • 逻辑清晰,容易理解,结构类似于常见的表格
  • 使用SQL语句,技术成熟,使用方便
  • 关系型数据库比较成熟,可以使用一些复杂的操作

缺点

  • 每次操作都需要专门的SQL解析
  • 关系型数据库结构严格,内部加锁
  • 在应对海量数据并发处理时读写速度差

2. 非关系型数据库#

没有采用关系模型(二维表)来组织数据结构的数据库

键值型:Redis

列存储:HBase

文档型:MongoDB

图形:Graph

优点

  • 读写速度快,能更好的针对并发处理
  • 使用灵活,容易扩展

缺点

  • 没有sql那样统一成熟的语句
  • 技术程度较差,缺少一些复杂的操作

应用场景

  • 对数据结构要求不严格,比较灵活
  • 对数据处理的速度,特别是海量数据的并发处理速度要求比较高
  • 特定场景:需要灵活扩展,需要作为缓存

三、MongoDB#

1. 特点#

  • 非关系型数据库,是属于文档型数据库
  • 开源数据库,使用广泛
  • 由c++编写的数据库管理系统
  • 支持丰富的存储类型和数据操作
  • 提供了丰富的编程语言接口
  • 方便扩展和部署

2. 安装#

Ubuntu:sudo apt-get install mongodb

Mac:brew install mongodb

Windows:www.mongodb.com

ubuntu安装位置:/var/lib/mongodb

配置文件:/etc/mongodb.conf

命令集:/usr/bin/

3. 基础命令#

名称:mongodb shell

命令:mongo

退出:quit()

mongod 设置MongoDB的基本信息

mongod -h //查看帮助

mongod --dbpath [dir] //设置数据库存储位置

mongod --port [port] //设置数据库端口

*默认端口为27017

四、数据结构#

数据组织结构:键值对-->文档-->集合-->数据库

例如:

MySQL

MongoDB

MySQL MongoDB 含义
databases databases 数据库
table collection 表/集合
column field 字段/域
row document 记录/文档
index index 索引

五、数据库操作#

1. 数据库操作#

use [database]创建数据库

use实际是选择使用哪个数据库,当这个数据库不存在的时候,自动创建

但是不会立即建立,只有插入数据的时候才会真正建立

show dbs查看数据库

db.class.insert({"name":"Lily","age":"17"}) 插入简单的数据

db.dropDatabase() 删除当前数据库,在use之后执行,就会删除当前数据库

数据库命名规则

  • 使用UTF-8字符串

  • 不能含有空格``.``/``\``\0字符

  • 不能超过64字节长度

  • 不要和系统库重名

db代表当前正在使用的数据库,进入数据库默认使用`tes

2. 备份恢复#

数据库的备份恢复

mongodump -h [host] -d [db] -o {path]备份

mongorestore -h [host:port] -d [db] [bak] 恢复

3. 运行监控#

3.1 运行状态

mongostat 查看数据库运行状态(只要修改磁盘的都是写操作,查是读操作)

insert query update delete 每秒增查改删的次数

getmore

command 每秒执行MongoDB命令的次数

dirty

used

flushes 每秒刷新磁盘的次数

vsize 虚拟内存使用情况

res 物理内存使用情况

qrw

arw

net_in

net_out

conn

time当前时间

3.2 读写时长

mongotop 查看数据库读写时长

2019-08-01T11:14:53.678+0800 connected to: 127.0.0.1

                ns    total    read    write    2019-08-01T11:14:54+08:00
admin.system.roles      0ms     0ms      0ms

admin.system.version 0ms 0ms 0ms
config.system.sessions 0ms 0ms 0ms
local.startup_log 0ms 0ms 0ms
local.system.replset 0ms 0ms 0ms
stu.class 0ms 0ms 0ms
student.class 0ms 0ms 0ms

得到每个集合在每秒之内的读写时间

六、集合操作#

db.createCollection(collectionName) 创建集合

show collections或者show tables 查看集合

db.collection.insert(...) 插入数据(如果该集合不存在,则自动创建)

db.collection.drop() 删除集合

db.collection.renameCollection(NewName) 集合重命名

集合命名规则

  • 使用UTF-8字符
  • 不能含有'\0'
  • 不要以system.开头,这是系统集合默认开头
  • 不要和关键字重名

七、文档操作#

1. 概述#

文档是MongoDB中基本的数据组织单元

文档由键值对构成,每个键值对表达一个数据项

MongoDB的文档属于bson类型数据

bson-->Json-->JavaScript

文档键值对特点

  • 无序的
  • 通过键值对取值
  • 不能重复
  • 键是UTF-8字符串,不能有\0字符

2. 数据类型#

2.1 整型

int : 整数

2.2 浮点型

double : 小数

2.3 布尔

boolean : true/false

2.4 字符串

string : utf-8字符串

2.5 ObjectID

id对象

> db.class0.find()
{ "_id" : ObjectId("5d42519a1ae0b26ac7985b89"), "name" : "Lily", "age" : 17 }

其实质就是一串16进制,通过一定的算法,生成不重复的24位的16进制值

MongoDB插入文档时,每个文档都要有一个_id与,可以自己指定一个不重复的值,也可以由系统自动生成

3.集合文档设计#

  • 一个集合中的文档可以有不同的域,域的个数也可以不一致
  • 集合中的文档层次不宜嵌套过多,如果层次过多时应考虑分为多个集合
  • 在一个集合中的文档应该尽量表达相同类型的数据类型

八、数据操作#

1. 插入文档#

db.collection.insertOne(doc)

功能:插入一条文档

参数:一条要插入的文档

> db.class0.insertOne({"name":"Lucy","age":18,"sex":"女"})
{
        "acknowledged" : true,
        "insertedId" : ObjectId("5d428df01bc9a3414430192e")
}

操作时,键可以不加引号

可以自己设置_id值,但是不能重复

db.collection.insertMany([{...},{...},{...}])

功能:插入多条文档

参数:数组中为多个文档

> db.class.insertMany([{name:'波多野结衣',age:33,sex:"女"},{name:"苍井空",age:36,sex:"
女"},{name:"麻生希",age:30,sex:"女" }])
{
        "acknowledged" : true,
        "insertedIds" : [
                ObjectId("5d42915d1bc9a34144301930"),
                ObjectId("5d42915d1bc9a34144301931"),
                ObjectId("5d42915d1bc9a34144301932")
        ]
}
> db.class.find()
{ "_id" : ObjectId("5d42915d1bc9a34144301930"), "name" : "波多野结衣", "age" : 33, "sex
" : "女" }
{ "_id" : ObjectId("5d42915d1bc9a34144301931"), "name" : "苍井空", "age" : 36, "sex" :
"女" }
{ "_id" : ObjectId("5d42915d1bc9a34144301932"), "name" : "麻生希", "age" : 30, "sex" :
"女" }

数组:使用[ ]表示 的一组数据有序集合

特点:有序,使用序列号取值

练习

创建grade数据库

创建class集合

集合中插入若干数据项,格式如下

{name:xxx,age:xxx,sex:x,hobby:[xx,xx,xx]}

规则:年龄(7-15)、hobby(draw、dance、sing、football、basketball、computer、python)

use grade
db.class.insertOne(
	{name:"Chancey",age:18,sex:"男",hobby:["draw","dance","sing"]}
	)
db.class.insertMany([
	{name:"小红",age:18,sex:"女",hobby:["draw","python"]},	
	{name:"小明",age:23,sex:"男",hobby:["sing","football"]},
	{name:"小花",age:35,sex:"女",hobby:["python","computer"]},	
	{name:"小绿",age:22,sex:"女",hobby:["computer","draw"]},	
	])

db.collection.insert()

功能:插入多条数据

参数:同insertOne + insertMany(可以是文档,也可以是数组里面嵌套文档)

官方已经不太推荐,所以使用上述两种方法插入数据更为稳定

db.collection.save()

功能:插入一条或者多条文档

参数:同insert

db.class0.save({name:'Alex',age:18,sex:"男"})

db.class0.save([
	{name:"小花",age:35,sex:"女",hobby:["python","computer"]},	
	{name:"小绿",age:22,sex:"女",hobby:["computer","draw"]}
	])

当_id冲突的时候,save则会覆盖掉已经存在的记录

2. 查询文档#

2.1 find

db.clooect.find(query,field)

功能:查找所有的符合条件的文档

参数:query(要查找的文档)、field(要查找的域)

返回值:返回所有查找到的文档

参数使用方法

2.1.1 query

是一个键值对文档{},空则表示查找所有

以键值对表示筛选条件,往往配合查找操作符完成

2.1.2 field

是一个键值对文档{}field:0表示不查找这个域,field:1表示查找这个域

> db.class0.find({age:18},{name:1,age:1})
{ "_id" : ObjectId("5d428df01bc9a3414430192e"), "name" : "Lucy", "age" : 18 }
{ "_id" : ObjectId("5d42a1621bc9a3414430193b"), "name" : "Alex", "age" : 18 }
> db.class0.find({age:18},{_id:0})
{ "name" : "Lucy", "age" : 18, "sex" : "女" }
{ "name" : "Alex", "age" : 18, "sex" : "男" }
> db.class0.find({age:18},{_id:0,sex:0})
{ "name" : "Lucy", "age" : 18 }
{ "name" : "Alex", "age" : 18 }
> db.class0.find({age:18},{_id:0,age:1,sex:1})
{ "age" : 18, "sex" : "女" }
{ "age" : 18, "sex" : "男" }

_id域如果不想查找,则_d:0

其他域要么全为0,要么全为1

2.2 findOne

db.collection.findOne(query,field)

功能:查找第一个符合条件的文档

参数:同find

返回值:返回查找到的文档

> db.class.findOne()
{
        "_id" : ObjectId("5d42915d1bc9a34144301930"),
        "name" : "波多",
        "age" : 33,
        "sex" : "女"
}
> db.class0.findOne({age:18})
{
        "_id" : ObjectId("5d428df01bc9a3414430192e"),
        "name" : "Lucy",
        "age" : 18,
        "sex" : "女"
}
> db.class0.findOne({age:20},{_id:0})
{ "name" : "素心", "age" : 20, "sex" : "男" }

如果没有参数则默认查找所有记录的第一条

2.3 query操作符

操作符:MongoDB中使用$注明的一个有特殊意义的字符串,用以表达丰富的含义,比如:$lt表示小于

2.3.1 比较操作符
序号 字符 汉义 符号
1 $eq 等于 =
2 $lt 小于 <
3 $gt 大于 >
4 $lte 小于等于 <=
5 $gte 大于等于 >=
6 $ne 不等于 !=
7 $in 包含
8 $nin 不包含
#查找年龄为20的
> db.class0.find({age:{$eq:20}},{_id:0}) 
{ "name" : "素心", "age" : 20, "sex" : "男" }
> db.class0.find({sex:{$eq:"女"}},{_id:0})
{ "name" : "Lucy", "age" : 18, "sex" : "女" }
{ "name" : "Chancey", "age" : 17, "sex" : "女" }

#查找年龄小于16的
> db.class0.find({age:{$lt:16}},{_id:0}) 
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }

#查找年龄大于17切小于20的(区间查找)
> db.class0.find({age:{$gt:17,$lt:20}},{_id:0}) 
{ "name" : "Lucy", "age" : 18, "sex" : "女" }
{ "name" : "Alex", "age" : 18, "sex" : "男" }

#查找年龄小于等于13的
> db.class0.find({age:{$lte:13}},{_id:0})
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }

#查找年龄大于等于20的
> db.class0.find({age:{$gte:20}},{_id:0})
{ "name" : "素心", "age" : 20, "sex" : "男" }
{ "name" : "Abby", "age" : 21, "sex" : "男" }

#查找年龄不等于13的
> db.class0.find({age:{$ne:13}},{_id:0})
{ "name" : "Lily", "age" : 17 }
{ "name" : "Lucy", "age" : 18, "sex" : "女" }
{ "name" : "Chancey", "age" : 17, "sex" : "女" }
{ "name" : "素心", "age" : 20, "sex" : "男" }
{ "name" : "Abby", "age" : 21, "sex" : "男" }
{ "name" : "Alex", "age" : 18, "sex" : "男" }
{ "name" : "Alex", "age" : 17, "sex" : "男" }

# 查找年龄等于13、16、20的
> db.class0.find({age:{$in:[13,16,20]}},{_id:0})
{ "name" : "素心", "age" : 20, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }

#查找年龄不等于13、16、20的
> db.class0.find({age:{$nin:[13,16,20]}},{_id:0})
{ "name" : "Lily", "age" : 17 }
{ "name" : "Lucy", "age" : 18, "sex" : "女" }
{ "name" : "Chancey", "age" : 17, "sex" : "女" }
{ "name" : "Abby", "age" : 21, "sex" : "男" }
{ "name" : "Alex", "age" : 18, "sex" : "男" }
{ "name" : "Alex", "age" : 17, "sex" : "男" }

包含的关系的写法

$ne的值里面填写数组,表示以该数组为集合查找任意符合条件的记录

2.3.2 逻辑操作符
序号 字符 汉义
1 $and
2 $or
3 $not
4 $nor 既不也不
# 查找年龄大于17且为男的
> db.class0.find({$and:[{age:{$gt:17}},{sex:"男"}]},{_id:0})
{ "name" : "素心", "age" : 20, "sex" : "男" }
{ "name" : "Abby", "age" : 21, "sex" : "男" }
{ "name" : "Alex", "age" : 18, "sex" : "男" }
# 查找姓名小于Lily且年龄为17,19,21的
> db.class0.find({$and:[{name:{$lt:"Lily"}},{age:{$in:[17,19,21]}}]},{_id:0})
{ "name" : "Chancey", "age" : 17, "sex" : "女" }
{ "name" : "Abby", "age" : 21, "sex" : "男" }
{ "name" : "Alex", "age" : 17, "sex" : "男" }

#查找年龄大于18或性别为女
> db.class0.find({$or:[{age:{$gt:18}},{sex:{$eq:"女"}}]},{_id:0})
{ "name" : "Lucy", "age" : 18, "sex" : "女" }
{ "name" : "Chancey", "age" : 17, "sex" : "女" }
{ "name" : "素心", "age" : 20, "sex" : "男" }
{ "name" : "Abby", "age" : 21, "sex" : "男" }
#查找年龄小于18或大于19
> db.class0.find({$or:[{age:{$lt:18}},{age:{$gt:19}}]},{_id:0})
{ "name" : "Lily", "age" : 17 }
{ "name" : "Chancey", "age" : 17, "sex" : "女" }
{ "name" : "素心", "age" : 20, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Abby", "age" : 21, "sex" : "男" }
{ "name" : "Alex", "age" : 17, "sex" : "男" }

#查找年龄不大于18的
> db.class0.find({age:{$not:{$gt:18}}},{_id:0})
{ "name" : "Lily", "age" : 17 }
{ "name" : "Lucy", "age" : 18, "sex" : "女" }
{ "name" : "Chancey", "age" : 17, "sex" : "女" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Alex", "age" : 18, "sex" : "男" }
{ "name" : "Alex", "age" : 17, "sex" : "男" }

#查找年龄不大于18性别也不为男
> db.class0.find({$nor:[{age:{$gt:18}},{sex:{$eq:"男"}}]},{_id:0})
{ "name" : "Lily", "age" : 17 }
{ "name" : "Lucy", "age" : 18, "sex" : "女" }
{ "name" : "Chancey", "age" : 17, "sex" : "女" }

使用逻辑操作符的时候,在特殊符号的值应为数组,数组里面包含条件

$not的格式与三目运算不一样,注意

2.3.3 混合查询
#年龄大于等于17的男生,或者名字叫Addy或者Emmm
> db.class0.find({$or:[{$and:[{age:{$gt:17}},{sex:{$eq:"男"}}]},{$or:[{name:"Addy"},{na me:"Emmm"}]}]},{_id:0})
{ "name" : "素心", "age" : 20, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Abby", "age" : 21, "sex" : "男" }
{ "name" : "Alex", "age" : 18, "sex" : "男" }
2.3.4 数组操作符
查找数组中包含元素
# 查找score数组大于90的记录
> db.class2.find({score:{$gt:90}},{_id:0})
{ "name" : "小红", "age" : 9, "score" : [ 97, 89, 87 ] }

当键对应的值为一个数组的时候,query填入一个包含关系的元素即可查找

查找数组中同时包含多项

$all

# 查找既包含87,又包含89的
> db.class2.find({score:{$all:[87,89]}},{_id:0})
{ "name" : "小红", "age" : 9, "score" : [ 97, 89, 87 ] }
根据数组的元素个数查找

$size

查找数组元素个数为3的记录
> db.class2.find({score:{$size:3}},{_id:0})
{ "name" : "小明", "age" : 10, "score" : [ 87, 69, 81 ] }
{ "name" : "小红", "age" : 9, "score" : [ 97, 89, 87 ] }
{ "name" : "小刚", "age" : 9, "score" : [ 90, 79, 90 ] }
切片操作

用于field参数,表示查找数组哪些项

$slice

# 查找指定数组的前两项
> db.class2.find({},{_id:0,score:{$slice:2}})
{ "name" : "小明", "age" : 10, "score" : [ 87, 69 ] }
{ "name" : "小红", "age" : 9, "score" : [ 97, 89 ] }
{ "name" : "小刚", "age" : 9, "score" : [ 90, 79 ] }
# 跳过前一项,查看之后的两项
> db.class2.find({},{_id:0,score:{$slice:[1,2]}})
{ "name" : "小明", "age" : 10, "score" : [ 69, 81 ] }
{ "name" : "小红", "age" : 9, "score" : [ 89, 87 ] }
{ "name" : "小刚", "age" : 9, "score" : [ 79, 90 ] }

可以指定哪些数组显示哪些元素

[m,n]表示跳过m项,查询m项之后的n项元素

如果超过数组元素个数,则显示最多的元素

通过索引查找

query中域名.序列号表示查找该数组某元素指定值的范围

# 查找socre下第1项大于80的记录
> db.class2.find({"score.1":{$gt:80}},{_id:0})
{ "name" : "小红", "age" : 9, "score" : [ 97, 89, 87 ] }

数组序列号也是从0开始数

2.3.5 其他操作符

$exists 判断一个域是否存在

# 查找age域的所有文档
> db.class2.find({age:{$exists:true}},{_id:0})
{ "name" : "小明", "age" : 10, "score" : [ 87, 69, 81 ] }
{ "name" : "小红", "age" : 9, "score" : [ 97, 89, 87 ] }
{ "name" : "小刚", "age" : 9, "score" : [ 90, 79, 90 ] }

$mod 根据除数余数筛选

# 查找年龄为奇数的文档
> db.class0.find({age:{$mod:[2,1]}},{_id:0})
{ "name" : "Lily", "age" : 17 }
{ "name" : "Chancey", "age" : 17, "sex" : "女" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Abby", "age" : 21, "sex" : "男" }
{ "name" : "Alex", "age" : 17, "sex" : "男" }

mod:[m,n]表示该数除以m,余n的文档

$type 根据类型筛选

> db.class0.find({age:{$type:2}},{_id:0})
> db.class0.find({age:{$type:1}},{_id:0})
{ "name" : "Lily", "age" : 17 }
{ "name" : "Lucy", "age" : 18, "sex" : "女" }
{ "name" : "Chancey", "age" : 17, "sex" : "女" }
{ "name" : "素心", "age" : 20, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Abby", "age" : 21, "sex" : "男" }
{ "name" : "Alex", "age" : 18, "sex" : "男" }
{ "name" : "Alex", "age" : 17, "sex" : "男" }

数组可以嵌套,即{$type:90}

2.4. 数据操作函数

2.4.1 范围值

db.collection.distinct(field)

功能:获取集合中某个域的值范围

参数:域名

返回值:取值的范围数组

# 查找class0的age域有哪些值
> db.class0.distinct("age")
[ 17, 18, 20, 13, 21 ]
# 查找class0的sex域有哪些值
> db.class0.distinct("sex")
[ "女", "男" ]
2.4.2 格式化显示

pretty()

功能:将查询结果格式化显示

> db.class0.find({},{_id:0}).pretty()
{ "name" : "Lily", "age" : 17 }
{ "name" : "Lucy", "age" : 18, "sex" : "女" }
{ "name" : "Chancey", "age" : 17, "sex" : "女" }
{ "name" : "素心", "age" : 20, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Abby", "age" : 21, "sex" : "男" }
{ "name" : "Alex", "age" : 18, "sex" : "男" }
{ "name" : "Alex", "age" : 17, "sex" : "男" }
2.4.3 限制显示

limit

功能:显示查询结果前n条

# 只显示前三条信息
> db.class0.find({},{_id:0}).limit(3)
{ "name" : "Lily", "age" : 17 }
{ "name" : "Lucy", "age" : 18, "sex" : "女" }
{ "name" : "Chancey", "age" : 17, "sex" : "女" }
2.4.4 跳页显示

skip(n)

跳过前n条,显示后边的文档

> db.class0.find({},{_id:0}).skip(6)
{ "name" : "Abby", "age" : 21, "sex" : "男" }
{ "name" : "Alex", "age" : 18, "sex" : "男" }
{ "name" : "Alex", "age" : 17, "sex" : "男" }
2.4.5 统计数量

count()

功能:统计查询结果数量

# 统计所有文档
> db.class0.find({},{_id:0}).count()
9
2.4.6 排序

sort({field:1/-1})

功能:对查找结果排序

参数:field表示排序的域,1升序、-1降序

> db.class0.find({},{_id:0}).skip(5).sort({age:1})
{ "name" : "Lucy", "age" : 18, "sex" : "女" }
{ "name" : "Alex", "age" : 18, "sex" : "男" }
{ "name" : "素心", "age" : 20, "sex" : "男" }
{ "name" : "Abby", "age" : 21, "sex" : "男" }

> db.class0.find({},{_id:0}).skip(5).sort({age:-1})
{ "name" : "Chancey", "age" : 17, "sex" : "女" }
{ "name" : "Alex", "age" : 17, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }

复合排序

> db.class0.find({},{_id:0}).skip(5).sort({age:-1,name:-1})
{ "name" : "Chancey", "age" : 17, "sex" : "女" }
{ "name" : "Alex", "age" : 17, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
2.4.7 函数连续调用
> db.class0.find({age:{$type:1}},{_id:0}).sort({afe:-1}).limit(3)
{ "name" : "Lily", "age" : 17 }
{ "name" : "Lucy", "age" : 18, "sex" : "女" }
{ "name" : "Chancey", "age" : 17, "sex" : "女" }
2.4.8 序列号

通过序列号直接获取文档集合中的某一个

# 获取文档集合的第一项
> db.class0.find({},{_id:0}).sort({age:1})[0]
{ "name" : "Emmm", "age" : 13, "sex" : "男" }

4. 修改文档#

4.1 修改函数

4.1.2 updateOne

db.collection.updateOne(query,update,upsert)

功能:修改第一个符合条件的文档

参数:查找条件、要修改的数据,同修改操作符一起使用、如果query没有筛选到文档,是否插入新的文档

update 键值对文档,表达将数据修改为什么样子

# 将name为小峰的age修改为16
db.class.updateOne({name:"小峰"},{$set:{age:16}})

upset 如果没有匹配到文档,则决定是否创建新的文档,默认false

> db.class.find({},{_id:0})
{ "name" : "小娅", "age" : 9, "sex" : "女", "hobby" : [ "draw", "football" ] }
> db.class.updateOne({name:"waller"},{$set:{age:16}},{upsert:true})
{
        "acknowledged" : true,
        "matchedCount" : 0,
        "modifiedCount" : 0,
        "upsertedId" : ObjectId("5d43ec85e7bb29c632f30a0d")
}
> db.class.find({},{_id:0})
{ "name" : "小娅", "age" : 9, "sex" : "女", "hobby" : [ "draw", "football" ] }
{ "name" : "waller", "age" : 16 }
4.1.3 updateMany

db.collection.updateMany(query,update,upsert)

功能:修改所有符合条件的文档

参数:同updateOne

# 将字符串的年龄修改为数字类型的年龄18
> db.class0.find({},{_id:0})
{ "name" : "waller", "age" : "\"20\"", "sex" : "男" }
{ "name" : "Mary", "age" : "\"18\"", "sex" : "男" }
> db.class0.updateMany({age:{$type:2}},{$set:{age:18}})
{ "acknowledged" : true, "matchedCount" : 2, "modifiedCount" : 2 }
> db.class0.find({},{_id:0})
{ "name" : "waller", "age" : 18, "sex" : "男" }
{ "name" : "Mary", "age" : 18, "sex" : "男" }
4.1.4 update

db.collection.update(query,update,upsert,multi)

功能:修改文档(可单一修改,也可多条修改)

参数:同、同、upsert=true等同于{upsert:true}、默认只修改一个文档(true为修改所有符合条件的文档)

upsert和multi的格式直接填写true或者false

> db.class0.update({name:"Jack"},{$set:{age:16}},true,true)
WriteResult({
        "nMatched" : 0,
        "nUpserted" : 1,
        "nModified" : 0,
        "_id" : ObjectId("5d43f0bee7bb29c632f30ab6")
})
> db.class0.find({},{_id:0})
{ "name" : "waller", "age" : 18, "sex" : "男" }
{ "name" : "Mary", "age" : 18, "sex" : "男" }
{ "name" : "Jack", "age" : 16 }

官方已经不推荐使用该方式插入数据,更加偏向于updateOneupdateMany

4.1.5 findOneAndUpdate

db.collection.findOneAndUpdate(query,update)

功能:查找到一个文档并修改

参数:查找条件、修改数据

返回值:修改之前的文档

> db.class0.find({},{_id:0})
{ "name" : "waller", "age" : 18, "sex" : "男" }
> db.class0.findOneAndUpdate({name:"waller"},{$set:{age:19}})
{
        "_id" : ObjectId("5d43eef44f5000004c0054f2"),
        "name" : "waller",
        "age" : 18,
        "sex" : "男"
}
> db.class0.find({},{_id:0})
{ "name" : "waller", "age" : 19, "sex" : "男" }
4.1.6 findOneAndReplace

db.collection.findOneAndReplace(query,doc)

功能:查找一个文档并替换之

参数:查找条件、新的文档

返回值:原来的文档

> db.class0.find({},{_id:0})
{ "name" : "Lily", "age" : 17 }
> db.class0.findOneAndReplace({name:"Lily"},{name:"ame",age:17,sex:"女"})
{
        "_id" : ObjectId("5d42519a1ae0b26ac7985b89"),
        "name" : "Lily",
        "age" : 17
}
> db.class0.find({},{_id:0}) 
{ "name" : "ame", "age" : 17, "sex" : "女" }

4.2 修改器

4.2.1 set

$set:修改一个域的值或者增加一个域

# 修改一个域
> db.class0.find({},{_id:0}) 
{ "name" : "小小", "age" : 18 }
{ "name" : "waller", "age" : 19, "sex" : "男" }
{ "name" : "Mary", "age" : 18, "sex" : "男" }
{ "name" : "Jack", "age" : 16 }
> db.class0.updateOne({sex:{$exists:false}},{$set:{sex:"男"}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.class0.find({},{_id:0})
{ "name" : "小小", "age" : 18, "sex" : "男" }
{ "name" : "waller", "age" : 19, "sex" : "男" }
{ "name" : "Mary", "age" : 18, "sex" : "男" }
{ "name" : "Jack", "age" : 16 }

#修改多个域
 @(shell):1:33
> db.class0.find({},{_id:0}) 
{ "name" : "Lucy", "age" : 18, "sex" : "女" }
> db.class0.updateOne({name:"Lucy"},{$set:{age:20,sex:"男"}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.class0.find({},{_id:0}) 
{ "name" : "Lucy", "age" : 20, "sex" : "男" }
4.2.2 unset

$unset删除一个域

> db.class0.find({},{_id:0})                                 )
{ "name" : "Lucy", "age" : 20, "sex" : "男" }
> db.class0.updateOne({name:"Lucy"},{$unset:{sex:""}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.class0.find({},{_id:0})
{ "name" : "Lucy", "age" : 20 }

当修改之后的域名为空时,即表示删除该域,注意使用$unset

4.2.3 rename

$rename重命名域

> db.class0.find({},{_id:0})
{ "name" : "ame", "age" : 17, "sex" : "女" }
{ "name" : "Lucy", "age" : 20 }
{ "name" : "Chancey", "age" : 17, "sex" : "女" }
{ "name" : "素心", "age" : 20, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Emmm", "age" : 13, "sex" : "男" }
{ "name" : "Abby", "age" : 21, "sex" : "男" }
{ "name" : "Alex", "age" : 18, "sex" : "男" }
{ "name" : "Alex", "age" : 17, "sex" : "男" }
{ "name" : "小小", "age" : 18, "sex" : "男" }
{ "name" : "waller", "age" : 19, "sex" : "男" }
{ "name" : "Mary", "age" : 18, "sex" : "男" }
{ "name" : "Jack", "age" : 16 }
{ "name" : "xx", "age" : 35 }
> db.class0.updateMany({},{$rename:{sex:"gender"}})
{ "acknowledged" : true, "matchedCount" : 14, "modifiedCount" : 11 }
> db.class0.find({},{_id:0})
{ "name" : "ame", "age" : 17, "gender" : "女" }
{ "name" : "Lucy", "age" : 20 }
{ "name" : "Chancey", "age" : 17, "gender" : "女" }
{ "name" : "素心", "age" : 20, "gender" : "男" }
{ "name" : "Emmm", "age" : 13, "gender" : "男" }
{ "name" : "Emmm", "age" : 13, "gender" : "男" }
{ "name" : "Abby", "age" : 21, "gender" : "男" }
{ "name" : "Alex", "age" : 18, "gender" : "男" }
{ "name" : "Alex", "age" : 17, "gender" : "男" }
{ "name" : "小小", "age" : 18, "gender" : "男" }
{ "name" : "waller", "age" : 19, "gender" : "男" }
{ "name" : "Mary", "age" : 18, "gender" : "男" }
{ "name" : "Jack", "age" : 16 }
{ "name" : "xx", "age" : 35 }
4.2.4 setOneInsert

$setOneInsert如果使用update*执行了插入文档操作,则作为插入的内容

# 如果执行了插入函数,则setOnInsert也会插入
> db.class0.find({},{_id:0})
{ "name" : "ame", "age" : 17, "gender" : "女" }
{ "name" : "Davil", "age" : 18, "gender" : "m" }
> db.class0.updateOne({name:"Davil"},{$set:{age:18},$setOnInsert:{gender:"m"}},{upsert:true})
{
        "acknowledged" : true,
        "matchedCount" : 0,
        "modifiedCount" : 0,
        "upsertedId" : ObjectId("5d43fb43e7bb29c632f30c02")
}
> db.class0.find({},{_id:0})
{ "name" : "ame", "age" : 17, "gender" : "女" }
{ "name" : "Davil", "age" : 18, "gender" : "m" }

uodate参数可以使用多个修改器

语句:db.class0.updateOne({name:"Davil"},{$set:{age:18},$setOnInsert:{gender:"m"}},{upsert:true})

如果执行了upsert,则会连同setOnInsert的内容也会插入

4.2.5 inc

$inc加法修改器

功能:指定域加指定数

# 给age通通加1
> db.class.find({},{_id:0})
{ "name" : "波多", "age" : 33, "sex" : "女" }
{ "name" : "苍空", "age" : 36, "sex" : "女" }
{ "name" : "麻希", "age" : 30, "sex" : "女" }
> db.class.updateMany({},{$inc:{age:1}})
{ "acknowledged" : true, "matchedCount" : 3, "modifiedCount" : 3 }
> db.class.find({},{_id:0})
{ "name" : "波多", "age" : 34, "sex" : "女" }
{ "name" : "苍空", "age" : 37, "sex" : "女" }
{ "name" : "麻希", "age" : 31, "sex" : "女" }

可以加整数、小数、负数、正数

注意:负数其实就是减法

4.2.6 mul

$mul 乘法修改器

# 给所有人年龄乘以2
> db.class.find({},{_id:0})
{ "name" : "波多", "age" : 34, "sex" : "女" }
{ "name" : "苍空", "age" : 37, "sex" : "女" }
{ "name" : "麻希", "age" : 31, "sex" : "女" }
> db.class.updateMany({},{$mul:{age:0.5}})
{ "acknowledged" : true, "matchedCount" : 3, "modifiedCount" : 3 }
> db.class.find({},{_id:0})
{ "name" : "波多", "age" : 17, "sex" : "女" }
{ "name" : "苍空", "age" : 18.5, "sex" : "女" }
{ "name" : "麻希", "age" : 15.5, "sex" : "女" }

可以加整数、小数、负数、正数

4.2.7 max

$max修改某个域的值,如果小于指定值则改为指定值,大于则不变

> db.class.find({},{_id:0})
{ "name" : "波多", "age" : 17, "sex" : "女" }
{ "name" : "苍空", "age" : 18.5, "sex" : "女" }
{ "name" : "麻希", "age" : 15.5, "sex" : "女" }
# 如果age域小于30改为30,大于则不变
> db.class.updateMany({sex:"女"},{$max:{age:30}})
{ "acknowledged" : true, "matchedCount" : 3, "modifiedCount" : 3 }
> db.class.find({},{_id:0})
{ "name" : "波多", "age" : 30, "sex" : "女" }
{ "name" : "苍空", "age" : 30, "sex" : "女" }
{ "name" : "麻希", "age" : 30, "sex" : "女" }

简记:能把小的改成大的

4.2.7 min

$min修改某个域的值,如果大于指定值则改为指定值,小于则不变

> db.class.find({},{_id:0}) 
{ "name" : "波多", "age" : 30, "sex" : "女" }
{ "name" : "苍空", "age" : 30, "sex" : "女" }
{ "name" : "麻希", "age" : 30, "sex" : "女" }
> db.class.updateMany({sex:"女"},{$min:{age:18}})
{ "acknowledged" : true, "matchedCount" : 3, "modifiedCount" : 3 }
> db.class.find({},{_id:0}) 
{ "name" : "波多", "age" : 18, "sex" : "女" }
{ "name" : "苍空", "age" : 18, "sex" : "女" }
{ "name" : "麻希", "age" : 18, "sex" : "女" }

简记:能把大的改成小的

4.2.8 数组修改器
(1) push

$push 向数组中添加一项

# 给小红添加一项10分的成绩
> db.class2.find({},{_id:0})
{ "name" : "小明", "age" : 10, "score" : [ 87, 69, 81 ] }
{ "name" : "小红", "age" : 9, "score" : [ 97, 89, 87 ] }
{ "name" : "小刚", "age" : 9, "score" : [ 90, 79, 90 ] }
> db.class2.updateOne({name:"小红"},{$push:{score:10}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.class2.find({},{_id:0})
{ "name" : "小明", "age" : 10, "score" : [ 87, 69, 81 ] }
{ "name" : "小红", "age" : 9, "score" : [ 97, 89, 87, 10 ] }
{ "name" : "小刚", "age" : 9, "score" : [ 90, 79, 90 ] }
(2) pushAll

$pushAll 向数组中添加多项

# 向小红添加88,98的成绩

(3) pull

$pull 从数组中删除某个值

# 删除小刚score中的90

(4)pullAll

$puAll同时删除数组中多个组

# 删除小刚的79,90
> db.class2.find({},{_id:0})                         })
{ "name" : "小明", "age" : 10, "score" : [ 87, 69, 81 ] }
{ "name" : "小红", "age" : 9, "score" : [ 97, 89, 87, 10 ] }
{ "name" : "小刚", "age" : 9, "score" : [ 90, 79, 90 ] }
> db.class2.updateOne({name:"小刚"},{$pullAll:{score:[79,90]}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.class2.find({},{_id:0})                                 })
{ "name" : "小明", "age" : 10, "score" : [ 87, 69, 81 ] }
{ "name" : "小红", "age" : 9, "score" : [ 97, 89, 87, 10 ] }
{ "name" : "小刚", "age" : 9, "score" : [ ] }
(5) pop

$pop弹出数组中的一项

# 弹出小红的最后一项
> db.class2.updateOne({name:"小红"},{$pop:{score:1}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.class2.find({},{_id:0})                       })
{ "name" : "小明", "age" : 10, "score" : [ 87, 69, 81 ] }
{ "name" : "小红", "age" : 9, "score" : [ 97, 89, 87 ] }
{ "name" : "小刚", "age" : 9, "score" : [ ] }
# 弹出小红的第一项
> db.class2.updateOne({name:"小红"},{$pop:{score:-1}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.class2.find({},{_id:0})                        })
{ "name" : "小明", "age" : 10, "score" : [ 87, 69, 81 ] }
{ "name" : "小红", "age" : 9, "score" : [ 89, 87 ] }
{ "name" : "小刚", "age" : 9, "score" : [ ] }

弹出类似于删除

但是弹出只能删除两端的内容

如果为1则弹出数组中最后一项,为-1则弹出第一项

(6) addToSet

addToSet 向数组中添加一项,但不能和已有的数值重复

> db.class2.find({},{_id:0})                        })
{ "name" : "小明", "age" : 10, "score" : [ 87, 69, 81 ] }
{ "name" : "小红", "age" : 9, "score" : [ 89, 87 ] }
{ "name" : "小刚", "age" : 9, "score" : [ ] }
> db.class2.updateOne({name:"小刚"},{$addToSet:{score:80}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.class2.find({},{_id:0})                             })
{ "name" : "小明", "age" : 10, "score" : [ 87, 69, 81 ] }
{ "name" : "小红", "age" : 9, "score" : [ 89, 87 ] }
{ "name" : "小刚", "age" : 9, "score" : [ 80 ] }

(7) each

$each对多个值逐一操作

# 对90,10 都执行操作
>db.class2.updateOne({name:"小红"},{$push:{$each:[10,90]}})

(8) position

$position 指定数组插入位置,配合$each使用

# 将90插入到索引1位置
> db.class2.updateOne({name:"小刚"},{$push:{score:{$each:[90],$position:1}}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.class2.find({},{_id:0})
{ "name" : "小明", "age" : 10, "score" : [ 87, 69, 81 ] }
{ "name" : "小红", "age" : 9, "score" : [ 89, 87 ] }
{ "name" : "小刚", "age" : 9, "score" : [ 80, 90 ] }

(9) sort

$sort给数组排序,配合$each使用

# 给score从按照降序排序
> db.class2.updateOne({name:"小红"},{$push:{score:{$each:[],$sort:-1}}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.class2.find({},{_id:0}) 
{ "name" : "小明", "age" : 10, "score" : [ 87, 69, 81 ] }
{ "name" : "小红", "age" : 9, "score" : [ 89, 87 ] }
{ "name" : "小刚", "age" : 9, "score" : [ 80, 90 ] }

-1为降序。1为升序

5. 删除文档#

5.1 删除函数

5.1.1 deleteOne

db.collection.deleteOne(query)

功能:删除第一个符合条件的文档

参数:筛选条件

# 删除第一个不存在性别域的文档
db.class.deleteOne({sex:{$exsits:false}})
5.1.2 deleteMany

db.collection.deleteMany(query)

功能:删除所有

# 删除所有小于18岁的
> db.class.find({},{_id:0})
{ "name" : "小红", "age" : 9, "sex" : "女", "hobby" : [ "dance", "draw" ] }
{ "name" : "小明", "age" : 24, "hobby" : [ "football", "sing" ] }
{ "name" : "小花", "age" : 36, "sex" : "女", "hobby" : [ "python", "computer" ] }
{ "name" : "小绿", "age" : 23, "sex" : "女", "hobby" : [ "computer", "draw" ] }
{ "name" : "小兰", "age" : 17, "sex" : "女", "hobby" : [ "sing", "draw" ] }
{ "name" : "小黄", "age" : 21, "sex" : "男", "hobby" : [ "python", "draw" ] }
{ "name" : "小黑", "age" : 17, "sex" : "男", "hobby" : [ "football", "pthon" ] }
{ "name" : "Chancey", "age" : 9, "sex" : "男", "hobby" : [ "computer", "python" ] }
{ "name" : "小娅", "age" : 10, "sex" : "女", "hobby" : [ "draw", "football" ] }
{ "name" : "小刚", "age" : 13, "sex" : "男", "hobby" : [ "draw", "football" ] }
> db.class.deleteMany({age:{$lt:18}})
{ "acknowledged" : true, "deletedCount" : 12 }
> db.class.find({},{_id:0})
{ "name" : "Chancey", "age" : 19, "sex" : "男", "hobby" : [ "draw", "dance", "sing" ] }
{ "name" : "小明", "age" : 24, "hobby" : [ "football", "sing" ] }
{ "name" : "小花", "age" : 36, "sex" : "女", "hobby" : [ "python", "computer" ] }
{ "name" : "小绿", "age" : 23, "sex" : "女", "hobby" : [ "computer", "draw" ] }
{ "name" : "小黄", "age" : 21, "sex" : "男", "hobby" : [ "python", "draw" ] }

{}表示删除所有文档

即 db.class.deleteMany({})

5.1.3 remove

db.collection.remove(query,justOne)

功能:删除文档

参数:筛选条件、默认false,删除所有符合条件的文档,true只删除一个符合条件的文档


5.1.4 findOneAndDelete

db.collection.findOneAndDelete(query)

功能:查找一个文档并删除

参数:查找条件

返回:查找到的文档

# 查找Levi并删除
>db.class0.findAndDelete({name:"Levi"})

6. 练习(查询)#

"_id","age","hobby","name","sex"
"5d4294091bc9a34144301933","18","[ ""draw"", ""dance"", ""sing"" ]","Chancey","男"
"5d4296a91bc9a34144301934","18","[ ""draw"", ""python"" ]","小红","女"
"5d4296a91bc9a34144301935","23","[ ""sing"", ""football"" ]","小明","男"
"5d4296a91bc9a34144301936","35","[ ""python"", ""computer"" ]","小花","女"
"5d4296a91bc9a34144301937","22","[ ""computer"", ""draw"" ]","小绿","女"
"5d43dbb4a5755f70bb10b68a","16","[ ""sing"", ""draw"" ]","小兰","女"
"5d43dbb4a5755f70bb10b68b","20","[ ""python"", ""draw"" ]","小黄","男"
"5d43dbb4a5755f70bb10b68c","16","[ ""football"", ""pthon"" ]","小黑","男"
"5d43dbb4a5755f70bb10b68d","6","[ ""basketball"", ""computer"" ]","小峰","男"
"5d43dbb4a5755f70bb10b68e","9","[ ""basketball"", ""python"", ""football"" ]","小浩","男"
"5d43dbb4a5755f70bb10b68f","10","[ ""sing"", ""draw"", ""computer"" ]","小娜","女"
  1. 查看班级中所有人信息

    db.class.find({},{_id:0})

  2. 查看班级中年龄8岁的人员信息

    db.class.find({age:{$eq:8}},{_id:0})

    db.class.find({age:8},{_id:0})

  3. 查看年龄大于10岁的学生信息

    db.class.find({age:{$gt:10}},{_id:0})

  4. 查看年龄在8-12岁之间的学生信息

    db.class.find({$and:[{age:{$gt:7}},{age:{$lt:13}}]},{_id:0})

    db.class.find($and:[{age:{$gte:8}},{age:{$lte:12}}],{_id:0})

  5. 查看年龄为9岁且喜欢画画的女生

    db.class.find({age:9,sex:"女",hobby:"draw"},{_id:0})

  6. 查看年龄小于8岁大于12岁的同学

    db.class.find({$or:[{age:{$lt:8}},{age:{$gt:12}}]},{_id:0})

  7. 查看年龄9岁或者11岁的学生信息

    db.class.find({$or:[{age:9},{age:11}]},{_id:0})

    db.class.find({age:{$in:[9,11]}},{_id:0})

  8. 查看有两项兴趣爱好的学生

    db.class.find({hobby:{$size:2}},{_id:0})

  9. 查找喜欢计算机的同学

    db.class.find({hobby:"computer"},{_id:0})

  10. 查找既喜欢画画也喜欢跳舞的同学

    db.class.find({$and:[{hobby:"draw"},{hobby:"dance"}]},{_id:0})

    db.class.find({hobby:{$all:["draw","dance"]}},{_id:0})

  11. 统计兴趣爱好有3项的学生信息

    db.class.find({hobby:{$size:3}},{_id:0})

  12. 找到班级中年龄第二大的同学

    db.class.find({},{_id:0}).sort({age:-1})[1]

  13. 找到班级中年龄最终小的三位女生

    db.class.find({sex:'女'},{_id:0}).sort({age:1}).limit(3)

7. 练习(修改)#

使用grade


  1. 将小红年龄修改为8岁,兴趣爱好改为跳舞画画

    db.class.updateOne({name:"小红"},{$set:{age:8,hobby:["dance","draw"]}})

  2. 小明多了一个兴趣爱好唱歌

    db.class.updateOne({name:"小明"},{$push:{hobby:"sing"}})

  3. 小王兴趣爱好多个吹牛、打篮球

    db.class.updateOne({name:"小王"},{$push:{hobby:["吹牛","basketball"]}})

  4. 小李兴趣增加跑步,但是确保不和以前的重复

    db.class.updateOne({name:"小李"},{$addToSet:{hobby:{$each:["tunning","sing"]}}})

  5. 班级所有同学年龄增加1

    db.class.updateMany({},{$inc:{age:1}})

  6. 删除小明的sex属性

    db.class.updateOne({name:"小明"},{$unset:{sex:''}})

  7. 小李第一个兴趣爱好不要了

    db.class.updateOne({name:"小明"},{$pop:{hobby:-1}})

  8. 小刚不喜欢画画了

    db.class.update({name:"小刚"},{$pullAll:{hobby:["doraw","computer"]}})

8.练习(删除)#

  1. 删除所有年龄小于8岁或者大于2岁的同学

    db.class0.deleteMany({$or:[{age:{$lt:8}},{age:{$gt:12}}]})

  2. 删除兴趣爱好中除了画画或者跳舞的同学

    db.class,deleteMany({hobby:{$nin:["draw","dance"]}})

九、时间类型#

1.1 获取当前时间#

new Date()自动生成当前时间(标准时间)

> db.class1.find({},{_id:0}) 
{ "name" : "python入门", "date" : ISODate("2019-08-03T08:05:20.409Z") }
{ "name" : "python精通", "date" : ISODate("2019-08-03T08:13:59.146Z") }

1.2 时间函数#

ISODate()

功能:将指定的时间转换为标准时间存入

参数:默认同new Date(0)获取当前时间或者字符定制时间

# 传入指定的时间
> db.class1.insert({name:"python从入门到精通",date:ISODate()}))
WriteResult({ "nInserted" : 1 })
> db.class1.find({},{_id:0}) 
{ "name" : "python入门", "date" : ISODate("2019-08-03T08:05:20.409Z") }
{ "name" : "python精通", "date" : ISODate("2019-08-03T08:13:59.146Z") }
{ "name" : "python从入门到精通", "date" : ISODate("2019-08-03T08:17:31.467Z") }
> db.class1.insert({name:"疯狂的python",date:ISODate("2019-01-01 08:08:08")})
WriteResult({ "nInserted" : 1 })
> db.class1.find({},{_id:0}) 
{ "name" : "python入门", "date" : ISODate("2019-08-03T08:05:20.409Z") }
{ "name" : "python精通", "date" : ISODate("2019-08-03T08:13:59.146Z") }
{ "name" : "python从入门到精通", "date" : ISODate("2019-08-03T08:17:31.467Z") }
{ "name" : "疯狂的python", "date" : ISODate("2019-01-01T08:08:08Z") }

"2019-01-01 08:08:08"

"20190101 8:8:8"

"20190101"

1.3 时间戳#

valueOf()

功能:将标准化时间转化为时间戳

# 将标准时间转换为时间戳
> db.class1.insertOne({book:"Python涅槃",date:ISODate().valueOf()})
{
        "acknowledged" : true,
        "insertedId" : ObjectId("5d45443bac70897becf59e7e")
}
> db.class1.find({},{_id:0})
{ "name" : "python入门", "date" : ISODate("2019-08-03T08:05:20.409Z") }
{ "name" : "python精通", "date" : ISODate("2019-08-03T08:13:59.146Z") }
{ "name" : "python从入门到精通", "date" : ISODate("2019-08-03T08:17:31.467Z") }
{ "name" : "疯狂的python", "date" : ISODate("2019-01-01T08:08:08Z") }
{ "book" : "Python涅槃", "date" : 1564820539435 }

1.4 null类型#

值:null

含义:空

表示某个域的值为空

> db.class1.insertOne({book:"python web",price:null})
{
        "acknowledged" : true,
        "insertedId" : ObjectId("5d454529ac70897becf59e7f")
}
> db.class1.find({},{_id:0})
{ "book" : "python web", "price" : null }

在查找的时候,如果用price域查找,没有price域的也会被查找出来

# 查找到price域为null或者没有该域的
> db.class1.find({price:null},{_id:0})
{ "name" : "python入门", "date" : ISODate("2019-08-03T08:05:20.409Z") }
{ "name" : "python精通", "date" : ISODate("2019-08-03T08:13:59.146Z") }
{ "name" : "python从入门到精通", "date" : ISODate("2019-08-03T08:17:31.467Z") }
{ "name" : "疯狂的python", "date" : ISODate("2019-01-01T08:08:08Z") }
{ "book" : "Python涅槃", "date" : 1564820539435 }
{ "book" : "python web", "price" : null }

1.5 内部文档#

也称Object类型

> db.calss3.insertOne({"book":"xi you ji ",intro:{author:"wu cheng en",price:38.6,publication:"China"}})
{
        "acknowledged" : true,
        "insertedId" : ObjectId("5d45476cac70897becf59e80")
}
> db.calss3.insertOne({"book":"san guo yan yi",intro:{author:"luo guan zhong",price:42.6,publication:"China"}})
{
        "acknowledged" : true,
        "insertedId" : ObjectId("5d45478aac70897becf59e81")
}
> db.calss3.insertOne({"book":"shui hu zhuan",intro:{author:"shi nai an",price:48,publication:"China"}})
{
        "acknowledged" : true,
        "insertedId" : ObjectId("5d4547a3ac70897becf59e82")
}
> db.calss3.find({},{_id:0})
{ "book" : "xi you ji ", "intro" : { "author" : "wu cheng en", "price" : 38.6, "publication" : "China" } }
{ "book" : "san guo yan yi", "intro" : { "author" : "luo guan zhong", "price" : 42.6, "publication" : "China" } }
{ "book" : "shui hu zhuan", "intro" : { "author" : "shi nai an", "price" : 48, "publication" : "China" } }

定义:文档中某个域的值为内部文档,则该值为Object类型数据

使用方法:当使用内部文档某个域的值时,需要采用"外部域.内部域"的方法,此时,该格式需要用引号表示为字符串

# 内部文档查找
> db.calss3.find({"intro.author":"wu cheng en"},{_id:0})
{ "book" : "xi you ji ", "intro" : { "author" : "wu cheng en", "price" : 38.6, "publication" : "China" } }
> db.calss3.find({"intro.publication":"China"},{_id:0})
{ "book" : "xi you ji ", "intro" : { "author" : "wu cheng en", "price" : 38.6, "publication" : "China" } }
{ "book" : "san guo yan yi", "intro" : { "author" : "luo guan zhong", "price" : 42.6, "publication" : "China" } }
{ "book" : "shui hu zhuan", "intro" : { "author" : "shi nai an", "price" : 48, "publication" : "China" } }

# 内部文档修改
> db.calss.updateOne({book:"xi you ji "},{$set:{"intro.price":42}})
{ "acknowledged" : true, "matchedCount" : 0, "modifiedCount" : 0 }
> db.calss3.find({},{_id:0})
{ "book" : "xi you ji ", "intro" : { "author" : "wu cheng en", "price" : 38.6, "publication" : "China" } }
{ "book" : "san guo yan yi", "intro" : { "author" : "luo guan zhong", "price" : 42.6, "publication" : "China" } }
{ "book" : "shui hu zhuan", "intro" : { "author" : "shi nai an", "price" : 48, "publication" : "China" } }

1.6 练习#

  1. 将小红爱好的第二项变为唱歌

    db.class.updateOne({name:"xiao hong"},{$set:{'hobby.1':"sing"}})

  2. 给小王增加一个域

    备注:{民族:“回族”,习俗:“注意饮食禁忌”}

    db.class.updateOne({name:"xiao hong"},{$set:{'备注':{"民族":"回族","习俗":"注意饮食禁忌"}}})

  3. 修改小王的备注域,增加一项

    宗教:“伊斯兰”

    db.class.updateOne({name:"小王"},{$set:{"备注.宗教":"伊斯兰"}})

十、 索引#

1.概述#

1.1 定义

建立文档所在位置的查找清单,使用索引可以方便的快速查找,减少遍历次数,提高查找效率

1.2 索引约束

  • 数据量很小的时候不需要创建索引
  • 创建索引会增加磁盘的使用空间
  • 对数据库操作大多是写操作而不是读操作的时候不宜创建索引

2.创建索引#

2.1 createIndex

db.collection.createIndex()

功能:创建索引

参数:索引域和索引选项

#为name创建索引 
> db.class0.createIndex({name:1})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}

# 指定索引名称创建
> db.class0.createIndex({age:1},{name:"ageIndex"})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 2,
        "numIndexesAfter" : 3,
        "ok" : 1
}

参数说明:1为正向索引,-1为反向索引

2.2 ensureIndex

db.collection.ensureIndex()不常用

2.3 createIndexes

createIndexes([{},{},{},...])不常用

同时创建多个索引

3.查看索引#

db.collection.getIndexes()

功能:查看索引


# 查看索引
> db.class0.getIndexes()
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "stu.class0"
        },
        {
                "v" : 2,
                "key" : {
                        "name" : 1
                },
                "name" : "name_1",
                "ns" : "stu.class0"
        },
                },
        {
                "v" : 2,
                "key" : {
                        "age" : 1
                },
                "name" : "ageIndex",
                "ns" : "stu.class0"
        }
]

在创建文档的时候,系统会自动为_id创建索引,所以这里出现两个索引

4.删除索引#

4.1 dropIndex

db.collection.dropIndex(index or name)

功能:删除一个索引

参数:索引名称或者索引键值对

# 通过索引键值对删除
> db.class0.dropIndex({age:1})
{ "nIndexesWas" : 3, "ok" : 1 }
> db.class0.getIndexes()
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "stu.class0"
        },
        {
                "v" : 2,
                "key" : {
                        "name" : 1
                },
                "name" : "name_1",
                "ns" : "stu.class0"
        }
]

# 通过索引名删除
> db.class0.dropIndex("name_1") # 注意没有{}
{ "nIndexesWas" : 2, "ok" : 1 }
> db.class0.getIndexes()
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "stu.class0"
        }
]

注意这里使用键值对时用{},使用索引名时用()

4.2 dropIndexes

db.collection.dropIndexes

删除所有索引

> db.class0.dropIndexes()
{
        "nIndexesWas" : 2,
        "msg" : "non-_id indexes dropped for collection",
        "ok" : 1
}
> db.class0.getIndexes()
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "stu.class0"
        }
]

该操作不会删除_id_索引

5. 其他索引#

5.1 复合索引

根据多个域创建索引

> db.class0.createIndex({name:1,age:-1})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
> db.class0.getIndexes()
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "stu.class0"
        },
        {
                "v" : 2,
                "key" : {
                        "name" : 1,
                        "age" : -1
                },
                "name" : "name_1_age_-1",
                "ns" : "stu.class0"
        }
]

只需要填入多个键值对即可

5.2 Object/数组索引

如果对object域或者数组域创建索引则针对object或者数组中的某一个元素的查询也是索引查询

# 如果岁intro创建了索引,则该查找也是索引查找
db.class3.find({"intro.author":"曹雪芹"})

5.3 唯一索引

要求创建索引的域不能有重复值

# 已经存在的索引则不会再创建
> db.class0.getIndexes()
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "stu.class0"
        }
]

5.4 稀疏索引

如果创建的稀疏索引则会对没有索引域的文档忽略

>db.calss0.createIndex({name:1},{sparse:true,name:"Age"})

十一、 聚合操作#

对文档进行数据整理统计,得到统计结果

1.聚合函数#

1.1 aggregate

db.collection.aggregate(aggr)

功能:执行聚合操作

参数:聚合条件,配合聚合操作符使用

1.2 聚合操作符

1.2.1 分组聚合

$group 需要配合统计操作符

统计求和 $sum传的可以是整数、文档

# 统计男生、女生的年龄之和
> db.class0.aggregate({$group:{_id:'$gender',num:{$sum:1}}})
{ "_id" : "男", "num" : 9 }
{ "_id" : "女", "num" : 2 }

#按性别分组,求男生女生的平均年龄
> db.class0.aggregate({$group:{_id:"$gender",num:{$avg:"$age"}}})
{ "_id" : "男", "num" : 17.444444444444443 }
{ "_id" : "女", "num" : 17 }

求最大最小值

$max / $min

#按照性别分组,求每组的最大值、最小值
> db.class0.aggregate({$group:{_id:"$gender",num:{$max:"$age"}}})
{ "_id" : "男", "num" : 21 }
{ "_id" : "女", "num" : 17 }
> db.class0.aggregate({$group:{_id:"$gender",num:{$min:"$age"}}})
{ "_id" : "男", "num" : 13 }
{ "_id" : "女", "num" : 17 }

求第一个值或最后一个值

$first / $last

# 按照性别分组,求每组的第一个、最后一个值
> db.class0.aggregate({$group:{_id:"$gender",num:{$first:"age"}}})
{ "_id" : "男", "num" : "age" }
{ "_id" : "女", "num" : "age" }
> db.class0.aggregate({$group:{_id:"$gender",num:{$last:"age"}}})
{ "_id" : "男", "num" : "age" }
{ "_id" : "女", "num" : "age" }
1.2.2 数据筛选

$match

match的基本操作同query

# 筛选年龄为18 的文档
> db.class0.aggregate({$match:{age:18}})
{ "_id" : ObjectId("5d42a1621bc9a3414430193b"), "name" : "Alex", "age" : 18, "gender" : "男" }
{ "_id" : ObjectId("5d43edc8a5755f70bb10b692"), "name" : "小小", "age" : 18, "gender" : "男" }
{ "_id" : ObjectId("5d43ef0f4f5000004c0054f3"), "name" : "Mary", "age" : 18, "gender" : "男" }
{ "_id" : ObjectId("5d43fb43e7bb29c632f30c02"), "name" : "Davil", "age" : 18, "gender" : "m" }

# 筛选年龄大于18的文档
> db.class0.aggregate({$match:{age:{$gt:18}}})
{ "_id" : ObjectId("5d428df01bc9a3414430192e"), "name" : "Lucy", "age" : 20 }
{ "_id" : 1, "name" : "素心", "age" : 20, "gender" : "男" }
{ "_id" : ObjectId("5d42a08d1bc9a3414430193a"), "name" : "Abby", "age" : 21, "gender" : "男" }
{ "_id" : ObjectId("5d43eef44f5000004c0054f2"), "name" : "waller", "age" : 19, "gender" : "男" }
{ "_id" : ObjectId("5d43f65ea5755f70bb10b693"), "name" : "xx", "age" : 35 }

$limit

获取集合中前几条文档

# 获取前三条文档
> db.class0.aggregate({$limit:3})
{ "_id" : ObjectId("5d42519a1ae0b26ac7985b89"), "name" : "ame", "age" : 17, "gender" : "女" }
{ "_id" : ObjectId("5d428df01bc9a3414430192e"), "name" : "Lucy", "age" : 20 }
{ "_id" : ObjectId("5d428ee01bc9a3414430192f"), "name" : "Chancey", "age" : 17, "gender" : "女" }

$skip 跳过前几个文档

# 对查找结果跳过前10条
> db.class0.aggregate({$skip:10})
{ "_id" : ObjectId("5d43eef44f5000004c0054f2"), "name" : "waller", "age" : 19, "gender" : "男" }
{ "_id" : ObjectId("5d43ef0f4f5000004c0054f3"), "name" : "Mary", "age" : 18, "gender" : "男" }
{ "_id" : ObjectId("5d43f0bee7bb29c632f30ab6"), "name" : "Jack", "age" : 16 }
{ "_id" : ObjectId("5d43f65ea5755f70bb10b693"), "name" : "xx", "age" : 35 }
{ "_id" : ObjectId("5d43fb43e7bb29c632f30c02"), "name" : "Davil", "age" : 18, "gender" : "m" }

$sort 对文档排序

> db.class0.aggregate({$sort:{age:1}})
{ "_id" : ObjectId("5d42a06d1bc9a34144301938"), "name" : "Emmm", "age" : 13, "gender" : "男" }
{ "_id" : ObjectId("5d42a08d1bc9a34144301939"), "name" : "Emmm", "age" : 13, "gender" : "男" }
{ "_id" : ObjectId("5d43f0bee7bb29c632f30ab6"), "name" : "Jack", "age" : 16 }
{ "_id" : ObjectId("5d42519a1ae0b26ac7985b89"), "name" : "ame", "age" : 17, "gender" : "女" }
{ "_id" : ObjectId("5d428ee01bc9a3414430192f"), "name" : "Chancey", "age" : 17, "gender" : "女" }
{ "_id" : ObjectId("5d42a3bb1bc9a3414430193c"), "name" : "Alex", "age" : 17, "gender" : "男" }
{ "_id" : ObjectId("5d42a1621bc9a3414430193b"), "name" : "Alex", "age" : 18, "gender" : "男" }

2.聚合管道#

db.class0.aggregate([{},{},{},...])

将前一个聚合产生的结果交给最后一个聚合继续操作,直到最后结果

# 将sort出来的结果给limit操作
> db.class0.aggregate([{$sort:{age:-1}},{$limit:3}])
{ "_id" : ObjectId("5d43f65ea5755f70bb10b693"), "name" : "xx", "age" : 35 }
{ "_id" : ObjectId("5d42a08d1bc9a3414430193a"), "name" : "Abby", "age" : 21, "gender" : "男" }
{ "_id" : 1, "name" : "素心", "age" : 20, "gender" : "男" }

聚合管道可以有多个聚合函数共同操作

# 查看名字重复的次数
> db.class0.aggregate([{$group:{_id:"$name",num:{$sum:1}}},{$match:{num:{$gt:1}}}])
{ "_id" : "Emmm", "num" : 2 }
{ "_id" : "Alex", "num" : 2 }

3.聚合操作符#

$project

选择显示的域(值的写法同field参数)

# 筛选结果不显示_id,仅仅显示name和age
> db.class0.aggregate([{$match:{}},{$project:{_id:0,name:1,age:1}}])
{ "name" : "素心", "age" : 20 }
{ "name" : "ame", "age" : 17 }
{ "name" : "Lucy", "age" : 20 }
{ "name" : "Chancey", "age" : 17 }

4. 练习#

  1. 将所有男生按照年龄升序排序,结果不显示_id

    db.class0.aggregate([$match:{gender:"男"},{$sort:{age:1}},{$project:{_id:0}}])

  2. 将所有喜欢画画的女生按照年龄排序,取年龄最后的三个,只显示姓名、年龄、爱好

    db.class0.aggregate([{$match:{hobby:"graw",sex:"女"}},{$sort:{age:1}},{$limit:3},{$project:{_id:0,name:1,hobby:1}}])

十二、固定集合#

指的是MongoDB中创建固定大小的集合,称之为固定集合

特点:

  1. 如果在固定集合中强行插入数据,早期的数据将会被淘汰,从而插入新的数据
  2. 可以控制集合大小
  3. 数据插入、查找速度快

使用:日志处理,临时缓存

1. 创建#

db.createCollection(collection,{capped:true,size:10000,max:20})

capped:reuw 表示创建一个固定集合

size:10000 表示固定集合的大小

max 表示固定集合可存放的文档数量

# 创建固定集合log,最多存放三条文档
> db.createCollection("log",{capped:true,size:1000,max:3})
{ "ok" : 1 }
> show collections
log

2. 插入数据#

# 已经插入了三条数据
> db.log.find({},{_id:0,date:0})
{ "status" : "400", "address" : "192.168.1.5" }
{ "status" : "500", "address" : "192.168.1.5" }
{ "status" : "501", "address" : "192.168.1.5" }

# 再次尝试添加数据,返回true
> db.log.insertOne({status:"502",address:"192.168.1.5",date:Date})
{
	"acknowledged" : true,
	"insertedId" : ObjectId("5d4791418615e4157d3980b6")
}

# 查看时,前边的400不见了,多出来了502
> db.log.find({},{_id:0,date:0})
{ "status" : "500", "address" : "192.168.1.5" }
{ "status" : "501", "address" : "192.168.1.5" }
{ "status" : "502", "address" : "192.168.1.5" }

十三、文件存储#

MongoDB提供了一些存储文件的方式

1. 存储文件路径#

将本地的文件所在的路径以字符串存入到数据库里

优点:操作简单,节省空间

缺点:当数据库或者文件发生变化的时候需要球盖数据库

2. 存储文件本身#

将文件转换为二进制存储到数据库里

优点:文件绑定数据库,不易丢失

缺点:占用数据库空间大,文件存取效率低

1.2 大文件存储

GridFS文件存储方案

目的:更加方便的存取MongoDB中的大文件(>16M)

说明:

1. MongoDB数据库中创建两个集合共同存储文件
2. fs.files集合中为每个文件建立一个信息文档,存储文件的基本信息
3. fs.chunks集合中每个文档建立与fs.files的关系,并将文件分块存储

方法:

(1) 存储

mongofiles -d dbname put file

# 将demo.mp4 存储到数据库中
[root@localhost files]# mongofiles -d grid put demo.mp4 
2019-08-05T10:35:35.908+0800	connected to: localhost
added file: demo.mp4

db.fs.files.find() #查看文件信息

db.fs.chunks.find()

files和chunks的files_id域的值是一样的,以此来确定两个集合之间的关联

(2) 提取

mongofiles -d dbname get file

[root@localhost files]# ls
[root@localhost files]# mongofiles -d grid get demo.mp4 # 从数据库中获取demo.mp4 文件
2019-08-05T10:52:06.082+0800	connected to: localhost
finished writing to demo.mp4
[root@localhost files]# ls
demo.mp4

对大文件的存储提取方便,但是读写效率仍然比较低,不建议用来存储小文件

1.3 小文件存储

pass

十四、mongo shell#

对JavaScript支持,mongo shell就是用JavaScript编写的,所以可以使用基本的js代码

  • mongo shell 界面中支持基本的js代码
  • 通过js处理mongo的一些数据逻辑

十五、python操作MongoDB#

使用第三库pymongo,安装方法不再赘述

1.步骤#

导入pymongo

1.1 连接

from pymongo import MongoClient
conn = MongoClient("IP",27017) # 实现连接

1.2 选择数据库

db = conn.stu #选择数据库
myset = db.class0 # 选择集合

1.3 操作

通过集合对象调用接口完成数据操作

文档 --> 字典

数字 --> 列表

布尔 --> python

null --> Mome

操作符 --> 字符串形式原样书写

lt"lt"

from pymongo import MongoClient

# 创建数据库连接
conn = MongoClient('127.0.0.1',27017)

# 床架数据库对象和集合对象
db = conn.stu
myset = db.class4 # 如果不存在该文档,则创建
1.3.1 插入操作

insert_one()插入一条文档

insert_many() 插入多条文档

insert() 插入一条或者多条

save() 插入文档,如果_id重复就会覆盖

myset.insert_one({"name":"杨幂","King":"Chancey"})
myset.insert_many([{"name":"刘诗诗","King":"吴奇隆"},{"name":"杨紫","King":"张一山"}])
myset.insert({"name":"乔碧萝","King":"菜虚鲲"})
myset.insert([{"name":"林志玲","King":"黑泽良平"},{"name":"柳岩","King":"小岳岳"}])

myset.save({"_id":1,"name":"郑爽","King":"张翰"})
myset.save({"_id":1,"name":"郑爽","King":"慕容云海"})
# 返回结果查看,张翰被替换成了慕容云海
1.3.2 查找操作
find

find()查找所有

功能:查找所有文档

参数:形式同mongo中的 find

返回值:查找结果的游标对象

cursor游标对象属性

  • 通过迭代获取每个查找的文档结果
  • 通过调用属性方法对结果进一步操作

next()

limit()

skip()

count()

sort() 书写方法不一样,类似于sort([("age",1),("name",1)])

要得到具体的文档内容,需要遍历cursor

cursor = myset.find({},{'_id':0})
# 循环遍历,得到每一个结果都是文档字典
for i in cursor:
    print(i["name"],'------',i["King"])
# 所有的特殊操作符均加引号执行
cursor = myset.find({},{'_id':0})

# 循环遍历,得到每一个结果都是文档字典
for i in cursor:
    print(i["name"],'------',i["King"])

print(cursor.next()) #获取游标的下一个结果

# 调用skip、limit之后得到的仍然是游标对象,必须保证该游标对象没有遍历过
for i in cursor.skip(1).limit(3):
    print(i)

# 按照king排序
for i in cursor.sort([("King",1)]):
    print(i)

注意:

  1. 调用limit、skip、sort时游标必须没有遍历过

  2. sort写法不同

    {age:1,name:1} --> [('age',1),('name',1)]

find_one

find_one()查找一个文档

功能:查找一个文档

参数:同find

返回值:文档字典

r = myset.find_one({"King":"菜虚鲲"},{"_id":0})
print(r)
1.3.3 修改文档

update_one()修改一个文档

update_many()修改多个文档

update()修改一个或多个文档

#***************   find   ***************
myset.update_one({"King":"刘恺威"},{"$set":{"king_name":"chancey"}})
myset.update_many({"King":"菜虚鲲"},{"$set":{"king_name":"蔡徐坤"}})
myset.update({"King":"张一山"},{"$set":{"king_name":"张两山"}})
myset.update({"king_name":"张两山"},{"$set":{"king_name":"张三山"}},multi=True)
myset.update({"king_name":"张两山"},{"$set":{"king_name":"张三山"}},upsert=True)
1.3.3删除操作

delete_one删除一个文档

delete_many删除多个文档

remove

#***************   delete   ***************
myset.delete_one({"name":"杨幂"})
myset.delete_many({"king_name":None}) # 删除没有king_name域
myset.remove({"King":"菜虚鲲"},multi=False)
1.3.4复合操作

find_one_and_delete()

myset.find_one_and_delete({"King":"张一山"})
1.3.5 索引操作

vreate_index(index)

功能:创建索引

参数:{name:1} --> [('name'),1] kwargs为索引选项

返回值:索引名称

index1 = myset.create_index("name")
index2 = myset.create_index([("name",-1)],name="NAME")
print("1", index1)
print("2", index2)

list_indees()

dro_index()

drop_indexes

myset.drop_index("NAME")
myset.drop_index([('name',1)])
myset.drop_indexes()
1.3.6 聚合操作

aggregate([{},{},...])

功能:完成聚合操作

参数:聚合管道,同MongoDB shell

返回值:数据结果游标

myset = db.class0
pipe = [{"$match":{"gender":{"$exists":True}}},
        {"$sort":{"age":1}},
        {"$project":{"_id":0}}
        ]

cursor = myset.aggregate(pipe)

for i in cursor:
    print()
1.3.7 文件存储

import bson

  1. 将文件内容转换为bson二进制格式存储

    content = bson.binary.Binary(bytes)

    功能:将python字节串转换为bson

    参数:要转换的字符串

    返回值:bson

    ##################存储图片##################
    from pymongo import MongoClient
    import bson.binary
    
    conn = MongoClient('127.0.0.1',27017)
    db = conn.images
    myset = db.girl
    
    
    with open("./demo.jpg","rb") as f:
        data = f.read()
    
    # 将data转换为bson
    content = bson.binary.Binary(data)
    
    # 插入到集合
    dic = {"filename":"girl.jpg",'data':content}
    myset.insert_one(dic)
    f.close()
    conn.close()
    
    ##################提取图片##################
    from pymongo import MongoClient
    import bson.binary
    
    conn = MongoClient('127.0.0.1',27017)
    db = conn.image
    myset = db.girl
    
    # 提取文件
    img = myset.find_one({"filename":"demo.jpg"})
    
    with open('mm.jpg','wb') as f :
        f.write(img['data'])
    
    conn.close()
    

1.4 关闭连接

conn.clse()

作者:ChanceySolo

出处:https://www.cnblogs.com/chancey/p/11305114.html

版权:本作品采用「ChanceySolo-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   ChanceySolo  阅读(674)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示