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()
posted @ 2019-08-05 19:41  ChanceySolo  阅读(658)  评论(0编辑  收藏  举报