信丰县建设局网站,新手怎么开始做微商,论坛静态网站源码,官方网站建站1、初识Mongo
概述#xff1a;与关系型数据库不同#xff0c;MongoDB 的数据以类似于 JSON 格式的二进制文档存储#xff0c;通常称这种格式为Bson#xff0c;Bson不仅支持JSON中已有的数据类型#xff0c;还增加了一些额外的数据类型#xff0c;例如日期和二进制数据与关系型数据库不同MongoDB 的数据以类似于 JSON 格式的二进制文档存储通常称这种格式为BsonBson不仅支持JSON中已有的数据类型还增加了一些额外的数据类型例如日期和二进制数据以提高存储效率和解析速度。。
文档型的数据存储方式的优势 文档的数据类型可以对应到语言的数据类型如数组类型Array和对象类型Object文档可以嵌套有时关系型数据库涉及几个表的操作在 MongoDB 中一次就能完成可以减少昂贵的连接花销文档不对数据结构加以限制不同的数据结构可以存储在同一张表 使用场景 网站数据 Mongo 非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性 缓存 由于性能很高Mongo 也适合作为信息基础设施的缓存层。在系统重启之后由Mongo搭建的持久化缓存层可以避免下层的数据源过载 大尺寸、低价值的数据 使用传统的关系型数据库存储一些大尺寸低价值数据时会比较浪费在此之前很多时候程序员往往会选择传统的文件进行存储 高伸缩性的场景 Mongo 非常适合由数十或数百台服务器组成的数据库Mongo 的路线图中已经包含对MapReduce 引擎的内置支持以及集群高可用的解决方案 用于对象及JSON 数据的存储 Mongo 的BSON 数据格式非常适合文档化格式的存储及查询 MongoDB的应用 游戏场景 使用 MongoDB 存储游戏用户信息用户的装备、积分等直接以内嵌文档的形式存储方便查询、更新 物流场景 使用 MongoDB 存储订单信息订单状态在运送过程中会不断更新以 MongoDB 内嵌数组的形式来存储一次查询就能将订单所有的变更读取出来。 社交场景 使用 MongoDB 存储存储用户信息以及用户发表的朋友圈信息通过地理位置索引实现附近的人、地点等功能 物联网场景 使用 MongoDB 存储所有接入的智能设备信息以及设备汇报的日志信息并对这些信息进行多维度的分析 直播 使用 MongoDB 存储用户信息、礼物信息等 是否选用MongoDB只要满足下表中的一个需求就可以使用
应用特征Yes/No应用不需要复杂事务及复杂join支持yes新应用需求会变数据模型无法确定想快速迭代开发应用需要2000-3000以上的读写QPS更高也可以应用需要TB甚至 PB 级别数据存储应用发展迅速需要能快速水平扩展应用需要大量的地理位置查询、文本查询应用需要99.999%高可用 MongoDB(MongoDB属于非关系型数据库)与关系型数据库的比较 Bson介绍BSON是一种类似于JSON的二进制形式的存储格式简称Binary JSON它和JSON一样支持内嵌的文档对象和数组对象但是BSON有JSON没有的一些数据类型如Date和BinData类型。BSON有三个特点轻量性、可遍历性、高效性。 数据类型说明document举例String字符串{key:“cba”}Integer整型数值{key:2}Boolean布尔型{key:true}Double双精度浮点数{key:0.23}ObjectId对象id用于创建文档的id{_id:new ObjectId()}Array数组{arr:[“jack”,“tom”]}Timestamp时间戳{ createTime: new Timestamp() }object内嵌文档{student:{name:“zhangsan”,age:18}}null空值{key:null}Date或者ISODate日期时间{birthday:new Date()}Code代码{setPersonInfo:function(){}} 2、Mongo的安装与启动
2.1、Mongo的安装
①、进入Mongo官网(Download MongoDB Community Server | MongoDB) ②、选择正确的版本下载(根据下图操作) ③、将下载的压缩包解压再将解压后的目录重命名为一个简洁的名字后放入D盘根目录中(目录名不要带 . ) 2.2、Mongo的启动
2.2.1、启动方式一
启动命令 mongod.exe --dbpathpath --logpathpathdbpath 指定数据存储位置logpath 指定日志存储在哪个位置 注意指定的路径一定要存在。 ①、进入mongodb7_0_12目录(解压后重命名并放在D盘的目录)以cmd的方式打开 点击路径位置输入cmd并回车 此时就打开了cmd ②、在mongodb7_0_12目录下新建两个目录用于存放数据和日志 由于日志是写入具体的文件所以需要进入新建的log目录中新建一个文本文件用于保存日志 ③、在刚才打开的cmd命令行中启动mongo
# 手动切换到bin目录
cd ./bin# 启动mongo并指定数据和日志的存放目录
mongod.exe --dbpathD:\mongodb_5_0_28\data --logpathD:\mongodb_5_0_28\log\mylog.txt
运行结果如下 ④、根据第一步的步骤再次打开一个cmd并输入如下命令以连接已启动的mongo数据库
# 进入bin目录
cd ./bin# 启动mongo
mongo运行结果如下 ⑤、通过如下命令查看所有的表
show dbs;
运行结果如下 2.2.2、启动方式二
①、完成启动方式一中的第②步提前准备放数据和日志的目录以及存放日志的文件
②、在mongodb_5_0_28目录下创建一个后缀为bat的文件并写入如下内容后保存退出 D:\mongodb_5_0_28\bin\mongod.exe --dbpathD:\mongodb_5_0_28\data --logpathD:\mongodb_5_0_28\log\mylog.txt
③、双击我们创建的start.bat文件运行结果如下 ④、完成启动方式一中的第③步即可操作mongo了 3、通过配置文件管理参数 问题 启动MongoDB时编写参数太麻烦 解决方案 通过配置文件统一管理 ①、首先在mongo的根目录下创建一个后缀名为conf的文件创建完成后编辑该文件 ②、在文件中写入如下内容并保存退出(路径需要根据自己的实际情况改写)
# 数据库路径
dbpathD:\mongodb_5_0_28\data
# 日志输出文件路径
logpathD:\mongodb_5_0_28\log\mylog.txt
# 错误日志采用追加模式
logappendtrue
# 启用日志文件默认启用
journaltrue
# 这个选项可以过滤掉一些无用的日志信息若需要调试使用请设置为false
quiettrue
# 端口号 默认为27017
bind_ip0.0.0.0
# 启用权限验证使用账号密码登录
# authtrue
③、修改mongo根目录下创建的start.bat文件
D:\mongodb_5_0_28\bin\mongod -f D:\mongodb_5_0_28\mongo.conf
运行结果如下 ④、进入如下路径D:\mongodb_5_0_28\bin双击mongo.exe文件 运行结果如下说明我们的配置文件已经生效 4、Linux安装Mongo
①、根据网络视频跟做完成一个Linux虚拟机的创建
②、根据下图获取mongo的Linux版本地址(点击此处进入) ③、通过如下命令下载mongo
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-5.0.28.tgz
如果报错说wget:未找到命令先执行如下命令安装wget再执行上方的命令下载mongo
yum install wget -y
运行结果如下 ④、解压下载的压缩文件并对解压后的文件重新命名
tar -zxvf mongodb-linux-x86_64-rhel70-5.0.28.tgz
运行结果如下 对解压后的文件重命名
mv mongodb-linux-x86_64-rhel70-5.0.28 mongodb5
运行结果如下 ⑤、将mongo的bin目录增加到环境变量中并生效配置文件
# 进入mongo根目录下的bin目录
cd mongodb5/bin/# 获取bin目录的完整路径(将获取到的路径复制,后面要用)
pwd# 编辑配置文件
vi ~/.bash_profile# 进入文件后先按i切换到插入模式
i# 找到要修改的PATH属性进行修改(以下是我修改后的内容作为参考)
PATH/home/muxi/mongodb5/bin:$PATH:$HOME/.local/bin:$HOME/bin# 修改完成后先按ESC键退出插入模式(ESC键在键盘左上角)
ESC# 输入:wq后回车即可保存并退出文件
:wq 修改后的文件内容如下主要是将mongo目录下的bin目录添加到了PATH属性中并用将多个属性值进行分割 通过如下命令生效配置文件
. ~/.bash_profile
⑥、提前创建存放数据和日志的目录以及存放日志的文件
# 由于要创建目录和文件需要切换到管理员
sudo root# 创建多级目录
mkdir -p /var/mongo/data
mkdir -p /var/mongo/log# 创建存放日志的文件
touch /var/mongo/log/mylog.log ⑦、后台启动mongo
# 后台运行mongo
mongod --dbpath /var/mongo/data/ --logpath /var/mongo/log/mylog.log -fork# 查看mongo进程验证是否启动成功
ps aux | grep mongod
运行结果如下 ⑧、连接mongo数据库
mongo
运行结果如下 此时我们的mongo就完成了安装和启动接下来可以考虑使用配置文件简化启动命令。
⑨、创建配置文件简化启动命令
# 结束当前运行的mongo
Ctrl C# 进入mongo的根目录
cd ..# 创建配置文件
touch mongo.cfg# 编辑配置文件
vim mongo.cfg 为文件添加的内容如下
#数据库路径
dbpath/var/mongo/data
#日志输出文件路径
logpath/var/mongo/log/mylog.log
#错误日志采用追加模式
logappendtrue
#启用日志文件默认启用
journaltrue
#这个选项可以过滤掉一些无用的日志信息若需要调试使用请设置为false
quiettrue
#端口号 默认为27017
bind_ip0.0.0.0
port27017
⑩、验证配置文件是否生效
# 关闭以及启动的mongo进程
# 首先获取mongo的进程号
ps aux | grep mongodkill -9 mongod的进程号
运行结果如下 并且输入mongo后也显示连接失败进一步说明我们已经成功关闭了mongo 指定配置文件在后台运行
mongod -f mongo.cfg --fork
运行结果如下 连接数据库
mongo
运行结果如下 5、图形管理工具之Robo 3T
下载https://download.studio3t.com/studio-3t/windows/2022.6.1/studio-3t-x64.zip
提示安装时无脑下一步即可可以调整软件的安装位置。
实操通过Robo 3T连接本地的mongo数据库(连接前一定要打开本地的mongo可以直接打开前面创建的启动脚本D:\mongodb_5_0_28\start.bat) 测试结果如下 点击连接后我们就可以通过Robo 3T对mongo数据库进行操作了 6、MongoDB基础命令 ①、查看数据库 概述列出所有在物理上存在的数据库。 show dbs; ②、切换数据库/创建数据库 概述如果数据库不存在则指向数据库但不会立即创建直到插入数据或创建集合时数据库才被创建。 use 数据库名; ③、删除当前数据库 概述删除当前指向的数据库如果指向的数据库不存在则什么也不做。 use 数据库名
db.dropDatabase() ④、创建集合 概述创建一个集合。 注意无需手动创建集合, 向不存在的集合中第一次添加数据时集合会自动被创建出来。 db.createCollection(集合名) ⑤、查看集合 showtables; // 只在老版本中支持
show collections;⑥、删除集合 db.集合名.drop(); 实操通过图形管理工具Robo 3T实操基础命令(需要提前完成第5节的实操以连接本地的mongo数据库)。
提示以下所有操作都在Robo 3T中的intelliShell中完成下面是Robo 3T的使用说明 1.查看所有的数据库
show dbs;
运行结果如下 2.切换数据库
// 切换到存在的数据库local
use local;
//切换到不存在的数据库(即创建数据库)
use newdb
运行结果如下 3.创建集合
// 创建一个名为student的集合
db.createCollection(student)
运行结果如下 由于我们是在新建的数据库中创建了集合此时刷新数据库就能看到名为newdb的数据库了 4.查看集合
show collections;
运行结果如下 5.删除集合
db.student.drop();
运行结果如下 7、文档的添加
概述MongoDB中的数据以文档的形式存储而MongoDB又将文档存储在集合中。集合类似于关系数据库中的表。如果集合不存在MongoDB 会在首次存储该集合的数据时创建该集合。
语法
db.集合名.函数名()
函数名含义save( )保存文档。文档不存在时新创建一个文档; 文档存在,更新文档insert( )插入文档可以保存单文档也可以是多文档insertOne( )插入一个文档insertMany( )插入多个文档
注意插入文档时如果不指定_id参数MongoDB会为文档分配一个唯一的ObjectId。
实操通过实操掌握如何为mongo添加文档。
// 创建并切换到一个新的数据库
use Tsinghua;// 为指定的集合添加文档
db.student.save({name:muxi,age:24,score:88})
运行结果如下 接下来查看文档内容 student集合中的文档内容如下 此时我们有一个新的需求要求将name的值改为muxikeqi根据上面表中提到的文档存在时会更新文档接下来执行如下程序来验证一下
db.student.save({name:muxikeqi,age:24,score:88})
运行后查看集合选项卡(查看时要按CtrlR进行刷新) 欸怎么新增了一条数据而不是修改原有数据哦原来mongo判断文档是否存在的依据是根据_id属性的值进行判断因此要实现name属性值更改的需求时还要指定_id完整代码如下
// 这里的_id要根据自己操作时的_id属性的值进行修改
db.student.save({_id : ObjectId(66b40121db9f8c197f3ce023),name:muxikeqi,age:24,score:88})
运行结果如下 运行后查看集合选项卡(查看时要按CtrlR进行刷新) 通过观察id和name属性的值此时我们修改name属性值的需求已经正确实现了。
接下来尝试为已有集合student插入文档
// insert()插入单条数据的格式与save()一样
db.student.insert({name:张三,age:18,score:90})
// 插入多条数据时需要用[]将多组数据括起来
db.student.insert([{name:李四,age:20,score:92},{name:王五,age:23,score:89}])
运行后的集合选项卡(查看时要按CtrlR进行刷新) 最后实操一下inserOne()和insertMany()其实它们的功能完全能通过insert()方法实现这里主要是要了解
db.student.insertOne({name:niko})
db.student.insertMany([{name:donk,age:17},{name:magixx}])
运行后的集合选项卡(查看时要按CtrlR进行刷新) 8、文档的修改
语法
db.集合名.函数名()函数名含义update( query, update {multi: boolean})参数query:查询条件类似sql语句update中where部分 参数update:更新操作符类似sql语句update中set部分 参数multi:可选默认是false表示只更新找到的第一条记录值为true表示把满足条件的文档全部更新updateOne( query, update)更新一条数据updateMany( query, update)更新多条数据replaceOne(query, update)只能更新整文档
提示更新的字段若不存在会生成一个相应字段。
实操通过本实操掌握mongo如何修改文档。
首先尝试updata()方法的用法将 集合下的 文档中 属性name的值为muxikeqi的值修改为muxi
db.student.update({name : muxikeqi},{name : muxi})
修改后的集合选项卡(查看时要按CtrlR进行刷新) 通过观察上图不难得出结论mongo中通过update()方法修改文档时默认是更新整个文档并且默认只会修改找到的第一个文档。
下面先将第一条数据还原方便后面的测试
db.student.update({name : muxi},{name : muxikeqi,age : 24,score : 88})
接下来尝试只修改第一个name属性值为muxikeqi的age属性
// 需要修改文档中单个属性值时可以通过$set属性实现
// 注意即使指定的文档中没有age字段也会创建该字段并修改
db.student.update({name : muxikeqi},{$set:{age : 28}})
修改后的集合选项卡(查看时要按CtrlR进行刷新) 接下来尝试将所有name属性值为muxikeqi的age属性值修改为30
// 同时修改多个文档时,需要添加{multi:true}
db.student.update({name:muxikeqi} , {$set:{age:30}} , {multi:true})
修改后的集合选项卡(查看时要按CtrlR进行刷新) 至此我们已经了解了update()方法的默认机制如何只修改文档中的单个属性如何同时修改所有文档的操作方法。
下面了解一下updateOne()和updateMany()的用法它们的功能都能通过update()方法实现
db.student.updateOne({name:张三},{$set:{score:100}})
db.student.updateMany({name:muxikeqi},{$set:{score:99}})
修改前 修改后 最后了解一下replaceOne
// 这里不用$set是因为会报错
db.student.replaceOne({name:李四},{age:25})
修改前 修改后 9、文档的删除
语法
db.集合名.函数名()
函数名含义remove( query)参数query:匹配符合的删除条件数据deleteOne( query)更新一条数据deleteMany( query)更新多条数据
实操通过本实操掌握mongo中删除文档的方法(需要提前拷贝多份方便后期的学习) // remove()默认删除多个文档
db.student.remove({name:muxikeqi})
// deleteOne()默认删除一个文档
db.student.deleteOne({score:100})
// deleteMany()默认删除多个文档
db.student1.deleteMany({name:muxikeqi})student集合运行后的结果为 student1运行后的结果 接下来尝试删除集合中的所有文档
// 两种方法的{}都不能省略否则会报错
db.student.remove({})
db.student1.deleteMany({})
运行后两个集合都没有任何文档 10、文档的查询
概述若要从集合中选择文档可以使用 find() 或者 findOne() 方法。若要选择集合中的所有文档请将空文档作为查询筛选器文档传递给该方法。
语法
db.集合名.函数名()
函数名含义find( {条件文档})查找到所有匹配数据findOne( {条件文档})只返回匹配的第一个数据
运算符 语法操作格式$eq等于{:}$lt小于{:{$lt:}}$lte小于或等于{:{$lte:}}$gt大于{:{$gt:}}$gte大于或等于{:{$gte:}}$ne不等于{:{$ne:}}$or或{$or:[{},{}]}$in在范围内{age:{$in:[val1,val2]}}$nin不在范围内{age:{$nin:[val1,val2]}} 模糊匹配 概述使用//或$regex编写正则表达式。 示例 db.person.find({name:/^zs/})
db.person.find({name:{$regex:^zs}}}) 自定义查询 概述使用$where后面写一个函数返回满足条件的数据 示例 db.person.find({$where:function(){return this. Age20}}) # 高版本已经不支持了
db.person.find({$where:this.age23});
db.person.find(this.age 23);
db.person.find(this.country吴国 || this. Age23); limit 概述用于读取指定数量的文档。 语法 db.集合名称.find().limit(NUMBER) skip 概述用于跳过指定数量的文档。 语法 db.集合名称.find().skip(2) sort 概述用于对结果集进行排序。 语法 db.集合名称.find().sort({字段:1,...}) 参数为1时表示升序排列参数为-1时表示降序排列 count 概述用于统计结果集中文档条数。 语法及演示 db.集合名称.find({条件}).count()
db.集合名称.count({条件})db.stu.find({gender: true}).count()
db.stu.count({age:{$gt:20},gender: true}) $exists 概述判断是否有某个字段。 语法 db.集合名称.find({field:{$exists: true}}) dictinct 概述用于去重。 语法 db.集合名称.distinct(field)
db.集合名称.distinct(field,{过滤条件 }) 实操前准备准备用于查询的集合并为集合添加文档
// 为集合添加数据用于后期查询
db.person.insert([{name:司马懿,country:魏国,age:35},
{name:张辽,country:魏国,age:34},
{name:徐晃,country:魏国,age:24},
{name:夏侯惇,country:魏国,age:23},
{name:夏侯渊,country:魏国,age:23},
{name:庞德,country:魏国,age:23},
{name:张郃,country:魏国,age:34},
{name:李典,country:魏国,age:41},
{name:乐进,country:魏国,age:34},
{name:典韦,country:魏国,age:12},
{name:曹洪,country:魏国,age:21},
{name:曹仁,country:魏国,age:11},
{name:诸葛亮,country:蜀国,age:20},
{name:关羽,country:蜀国,age:32},
{name:张飞,country:蜀国,age:23},
{name:马超,country:蜀国,age:53},
{name:黄忠,country:蜀国,age:23},
{name:赵云,country:蜀国,age:32},
{name:魏延,country:蜀国,age:42},
{name:关平,country:蜀国,age:12},
{name:周仓,country:蜀国,age:42},
{name:关兴,country:蜀国,age:23},
{name:张苞,country:蜀国,age:12},
{name:周瑜,country:吴国,age:32},
{name:吕蒙,country:吴国,age:11},
{name:甘宁,country:吴国,age:23},
{name:太史慈,country:吴国,age:23},
{name:程普,country:吴国,age:24},
{name:黄盖,country:吴国,age:28},
{name:韩当,country:吴国,age:23},
{name:周泰,country:吴国,age:29},
{name:蒋钦,country:吴国,age:19},
{name:丁奉,country:吴国,age:17},
{name:徐盛,country:吴国,age:27}
])实操通过本实操掌握mongo查询数据的方法。
首先尝试用find()获取全部的文档
db.person.find()
运行结果如下 接下来用findOne()获取所有的文档
db.person.findOne()
运行结果如下 总结在查询所有文档时用find()查询时能获取集合中所有的文档而用findOne()查询时只能获取到第一个文档。
下面尝试获取指定条件的文档
// 获取集合中age属性小于12的所有文档
db.person.find({age:{$lt:12}})
运行结果如下 下面尝试有多个判断条件时有一个满足条件即可的情况(下面演示age属性的值小于12或大于50的情况)
db.person.find({$or:[{age:{$lt:12}},{age:{$gt:50}}]})
运行结果如下 下面尝试判断条件的同一属性满足多个特定值即可的情况
db.person.find({age:{$in:[34,35,36]}})
运行结果如下 下面尝试利用模糊匹配查询所有name值第一个字是 张 的文档
db.person.find({name:/^张/})
运行结果如下 下面展示模糊匹配的另一种写法
db.person.find({name:{$regex:^周}})
运行结果如下 下面演示limit()方法获取指定条数的数据
// 获取匹配到的前三条数据(前三个文档)
db.person.find().limit(3)
运行结果如下 下面演示通过skip()跳过指定条数的数据后再通过limit()方法获取指定条数的文档
db.person.find().skip(1).limit(2)
运行结果如下 下面演示通过sort()对年龄做排序处理并且用limit()限制排序的个数
db.person.find().limit(3).sort({age:-1})
运行结果如下 下面演示通过count()方法获取当前集合有多少个文档(多少条数据)
db.person.find().count()
运行结果如下 下面演示获取文档中存在某个字段的文档
db.person.find({name:{$exists:true}})
运行结果如下 下面演示通过dictinct()对属性值进行去重
db.person.distinct(age)
运行结果如下 最后演示一下自定义查询
// 这里的this表示person这个集合
db.person.find({$where:this.age42})
运行结果如下 下面演示自定义查询要同时满足多个条件时的用法
db.person.find({$where:this.age40 this. Country魏国})
运行结果如下 11、聚合操作
概述MongoDB 中聚合(aggregate)主要用于处理多个文档(诸如统计平均值求和等)并返回计算后的数据结果。 11.1、分组和过滤
语法
db.集合名称.aggregate([{管道:{表达式}}])
11.1.1、管道命令之$group
概述$group 是所有聚合命令中用的最多的一个命令用于将集合中的文档分组可用于统计结果。
示例
db.stu.aggregate({$group:{_id:$country,// 这里的counter是随便取的一个变量名counter:{$sum:1}}}
)
注意
db.集合名.aggregate 是语法所有的管道命令都需要写在其中_id 表示分组的依据按照哪个字段进行分组例如使用$gender表示选择gender字段进行分组$sum1 表示把每条数据作为1进行统计统计的是该分组下面数据的条数。 11.1.2、管道命令之$match
概述$match 用于进行数据的过滤是在能够在聚合操作中使用的命令和 find 区别在于$match 操作可以把结果交给下一个管道处理而 find 不行。
示例查询年龄大于20的魏国的人数。
db.person.aggregate([{$match:{age:{$gt:20}}},{$group:{_id:$country,counter:{$sum:1}}}]) 11.1.3、常用表达式
语法
表达式:$列名
常用表达式
$sum 计算总和 $sum:1 表示以⼀倍计数$avg 计算平均值$min 获取最⼩值$max 获取最⼤值$push 在结果⽂档中插⼊值到⼀个数组中 实操通过本实操掌握分组和过滤的用法。
首先尝试利用管道命令$group对person集合中的country字段进行分组并且统计每个分组有多少个文档
db.person.aggregate([{ $group : // 分组中每多一条数据,number就会加1{_id:$country , number:{$sum:1}}}]
)
运行结果如下 接下来对上面的程序做升级要求对country分组后每个分组中还要包含所有被包含的name属性值
db.person.aggregate([{$group:{_id:$country,names:{$push:$name},number_country:{$sum:1}}}])
运行结果如下 下面再次对上面的程序做升级在分组前先过滤出所有年龄大于20的文档然后再对过滤出的文档做分组处理
db.person.aggregate([{$match:{age:{$gt:20}}},{$group:{_id:$country,names:{$push:$name},number_persons:{$sum:1}}}
])运行结果如下 总结
// 单个聚合操作
db.集合名.aggregate(管道命令:{聚合关键字 : info})// 多个聚合操作
db.集合名.aggregate([管道命令1:{聚合关键字:info},管道命令2:{聚合关键字:info},...]) 11.2、排序与分页
11.2.1、管道命令之$sort
概述$sort 用于将输入的文档排序后输出1表示升序排序-1表示降序排序。
示例
// 查询人物按照年龄升序
db.person.aggregate([{$sort:{age:1}}])// 查询每个国家的人数并排序
db.person.aggregate([{$group:{_id:$country,counter:{$sum:1}}},{$sort:{counter:-1}}
])11.2.2、管道命令之 $skip 和 $limit
概述$limit用于限制返回数据的条数$skip用于跳过指定的文档数并返回剩下的文档数。
注意同时使用 $limit 和 $skip 时先使用 $skip 再使用 $limit。
示例
// 查询2条信息
db.person.aggregate([{$limit:2}
])// 查询从第三条开始的信息
db.person.aggregate([{$skip:3}
])// 查询每个国家的人数按照人数升序返回第二条数据
db.person.aggregate([{$group:{_id:$country,counter:{$sum:1}}},{$sort:{counter:-1}},{$skip:1},{$limit:1}
])11.2.3、管道命令之$project
概述$project用于修改文档的输入输出结构字段值0表示不显示字段值1表示显示。
示例
// 查询人物的姓名、年龄不显示ID
db.person.aggregate([{$project:{_id:0,name:1,age:1}}])// 查询每个国家的人数只显示数量
db.person.aggregate([{$group:{_id:$country,counter:{$sum:1}}},{$project:{_id:0,counter:1}}])注意
_id 与其他字段共同设置时0只能设置在 _id 上设置字段时除了 _id 字段其他默认取反。 实操通过本实操掌握mongo中排序与分页的操作。
首先尝试 $sort 的用法
// 对person集合中age字段做降序排序
db.person.aggregate([{$sort:{age:-1}}])
运行结果如下 下面对country进行分组并统计每个contry的人数最后通过人数做降序输出
db.person.aggregate([{$group:{_id:$country,number_man:{$sum:1}}},{$sort:{number_man:-1}}
])
运行结果如下 下面演示聚合分页也是对上面的程序做升级
db.person.aggregate([{$group:{_id:$country,num_person:{$sum:1}}},{$sort:{num_person:-1}},{$skip:1},{$limit:1}
])
运行结果如下 下面演示 $project 控制文档输出
db.person.aggregate([{$group:{_id:$country,num_person:{$sum:1},age_avg:{$avg:$age}}},{$sort:{num_person:-1}},{$project:{num_person:1,age_avg:1}} // 注意不要同时设置0和1,否则会报错,但是_id设置为0,其它属性设置为1是被允许的
])
运行结果如下 最后演示一下 $project 的特殊用法
db.person.aggregate([{$group:{_id:$country,num_person:{$sum:1},age_avg:{$avg:$age}}},{$sort:{num_person:-1}},// 注意当设置某部分字段的显示方式后,没有指定的默认取反(例如这里将_id设置为不显示,num_person和age_avg没有指定,它们默认不显示,取反后就是显示){$project:{_id:0}}
])
运行结果如下 12、索引
12.1、索引的基本用法
概述索引通常能够极大的提高查询的效率如果没有索引MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录这种扫描全集合的查询效率是非常低的特别在处理大量的数据时。
创建索引的语法
db.集合名.createIndex(keys, options)
提示语法中 Key 值为要创建的索引字段1 为指定按升序创建索引如果想按降序来创建索引指定为 -1 即可。
注意
在 3.0.0 版本前创建索引方法为 db.collection.ensureIndex()之后的版本使用了 db.collection.createIndex() 方法ensureIndex() 还能用但只是 createIndex() 的别名MongoDB默认所有的集合在_id字段上有一个索引。
示例
db.person.createIndex({name:1})
查看索引的语法
// 默认情况下_id是集合的索引
db.集合名.getIndexes()
删除索引的语法
db.集合名.dropIndex({索引名称:1})
实操通过本实操掌握mongo如何创建查看和删除索引。
首先查看当前person集合中有哪些索引
// 查看索引
db.person.getIndexes()
运行结果如下 然后新建一个索引然后再查看索引
// 创建新的索引
db.person.createIndex({name:1})
// 再次查看索引
db.person.getIndexes()
运行结果如下 下面删除新建的索引然后再查看索引
// 删除新建的索引
db.person.dropIndex({name:1})
// 再次查看索引
db.person.getIndexes()
运行结果如下 接下来我们尝试验证一下索引是否能提高查询效率首先准备若干条数据
for(i0;i120000;i){db.index01.insert({name:muxikeqii,exp:i})
};
查看当前数据集有多少条数据
db.index01.find().count()
运行结果如下 获取正常检索muxikeqi99999所消耗的时间
db.index01.find({name:muxikeqi99999}).explain(executionStats)
运行结果如下可知查找花费了37ms 接下来为name属性添加索引并检索
db.index01.createIndex({name:1})
db.index01.find({name:muxikeqi99999}).explain(executionStats)
运行结果如下可知查询花费了0ms 总结索引能极大地提高查询速度数据量越大越需要使用索引。 12.2、唯一索引与复合索引
12.2.1、唯一索引
概述在默认情况下mongdb的索引的值是可以相同的创建唯一索引之后数据库会在插入数据的时候检查创建索引域的值是否存在如果存在则不会插入该条数据但是创建索引仅仅能够提高查询速度,同时降低数据库的插入速度。
语法
db.集合名.createIndex({字段名:1}, {unique: true})
基操利用唯一索引进行数据去重(根据唯一索引指定的字段的值如果相同则无法插入数据)
db.person.createIndex({name:1}, {unique: true})
db.person.insert({name: test10000}) 12.2.2、复合索引
概述在进行数据去重的时候可能用多个字段来做数据的唯一性这个时候可以考虑建立复合索引来实现。
语法
db.collection_name.createIndex({字段1:1,字段2:1})
注意点 根据需要选择是否需要建立唯一索引 索引字段是升序还是降序在单个索引的情况下不影响查询效率但是带复合索引的条件下会有影响 数据量巨大并且数据库的读出操作非常频繁的时候才需要创建索引如果写入操作非常频繁创建索引会影响写入速度 实操通过本实操掌握唯一索引与复合索引的创建。
在创建唯一索引之前需要提前将index01集合中为name字段添加的索引删除然后再为name添加唯一索引
db.index01.dropIndex({name:1})
db.index01.createIndex({name:1},{unique: true})
接下来验证唯一索引添加一个已经存在的数据
db.index01.insert({name:muxikeqi123})
运行结果如下很明显唯一索引已经生效了 或者直接去查看索引验证
db.index01.getIndexes()
运行结果如下 下面尝试为name和age字段创建复合索引
db.index01.createIndex({name:1,age:1})
运行结果如下 最后验证一下复合索引是否创建成功
db.index01.getIndexes()
运行结果如下 13、Python操作mongo
官方文档PyMongo 4.8.0 documentation
13.1、环境安装
概述在Pycharm中的终端(AltF12)中输入如下代码安装pymongo第三方库。
pip install pymongo4.2.0
运行结果如下 13.2、使用样例
引入第三方模块 import pymongo 连接、创建客户端 client pymongo.MongoClient(localhost, 27017)
client pymongo.MongoClient(mongodb://localhost:27017/) 获取指定数据库person db client.person
db client[person] 获取指定集合movie collection db.movie
collection db[movie] 添加数据 #增加一条
m1{name:300集,actor:高总,level:10}
m1_id movie.insert_one(s1).inserted_id
#增加多条
mids movie.insert_many([movie1,movie2]) 注意原insert方法也可以实现上面的功能但是在PyMongo 3.x的版本已经不推荐使用了。 查找数据 find() 返回一个生成器对象find_one() 返回一条数据 result movie.find_one()
result movie.find_one({name:1200集})
result movie.find_one({_id:OjectId(5932a80115c2606a59e8a049)})
result movie.find_one({level:{$gt:1}})
results movie. Find() 比较符号1 符号含义示例$lt小于{age: {$lt: 20}}$gt大于{age: {$gt: 20}}$lte小于等于{age: {$lte: 20}}$gte大于等于{age: {$gte: 20}}$ne不等于{age: {$ne: 20}}$in在范围内{age: {$in: [20, 23]}}$nin不在范围内{age: {$nin: [20, 23]}} 功能符号 符号含义示例示例含义$regex匹配正则表达式{name: {$regex: ^M.*}}name以M开头$exists属性是否存在{name: {$exists: True}}name属性存在$type类型判断{age: {$type: int}}age的类型为int$mod数字模操作{age: {$mod: [5, 0]}}年龄模5余0$text文本查询{$text: {$search: Mike}}text类型的属性中包含Mike字符串$where高级条件查询{$where: obj.fans_count obj.follows_count}自身粉丝数等于关注数 获取文档个数 count movie.count_documents() 排序 results collection.find().sort(name, pymongo.ASCENDING) 偏移、分页 collection.find().sort(name, pymongo.ASCENDING).skip(2).limit(2) 更新 args {name: 曹操}
student.update_one(args, {$set:{field:value}}})
result collection.update_many(query, {$set: {field: value}}) 注意update也可以实现上面的功能但是在PyMongo 3.x的版本已经不推荐使用了。 删除 result collection.remove({name: 300集}) # 4.2版本不支持
result collection.delete_one({name: 300集})
result collection.delete_many({age: {$lt: 25}}) 实操通过本实操掌握Python操作mongo的用法。
# 引入三方模块
import pymongo# 创建连接(默认连接本机)
client pymongo.MongoClient()# 获取数据库实例(如果指定的数据库实例不存在就自动创建)
db1 client.Tsinghua
db2 client[PyMyMongo]# 获取集合(如果指定的集合不存在就自动创建)
c1 db1.user
c2 db2[user]# 操作数据
def add_data():添加数据data1 {name:张三,age:20,score:89}data2 {name:李四,age:22,score:92}c1.insert_one(data1)c1.insert_many([data1,data2])if __name__ __main__:add_data()
运行结果如下 接下来尝试修改已有数据
# 引入三方模块
import pymongo# 创建连接(默认连接本机)
client pymongo.MongoClient()# 获取数据库实例(如果指定的数据库实例不存在就自动创建)
db1 client.Tsinghua
db2 client[PyMyMongo]# 获取集合(如果指定的集合不存在就自动创建)
c1 db1.user
c2 db2[user]# 操作数据
def add_data():添加数据data1 {name:张三,age:20,score:89}data2 {name:李四,age:22,score:92}c1.insert_one(data1)c1.insert_many([data1,data2])def update_data():修改数据# 指定要修改的数据args {name:张三}# c1.update_one(args,{$set:{age:30}})c1.update_many(args,{$set:{age:40}})if __name__ __main__:# add_data()update_data()
运行结果如下 接下来尝试删除集合中的所有文档
# 引入三方模块
import pymongo# 创建连接(默认连接本机)
client pymongo.MongoClient()# 获取数据库实例(如果指定的数据库实例不存在就自动创建)
db1 client.Tsinghua
db2 client[PyMyMongo]# 获取集合(如果指定的集合不存在就自动创建)
c1 db1.user
c2 db2[user]# 操作数据
def add_data():添加数据data1 {name:张三,age:20,score:89}data2 {name:李四,age:22,score:92}c1.insert_one(data1)c1.insert_many([data1,data2])def update_data():修改数据# 指定要修改的数据args {name:张三}# c1.update_one(args,{$set:{age:30}})c1.update_many(args,{$set:{age:40}})def delete_data():删除数据# 删除一条指定特征的数据# c1.delete_one({name:张三}}# 删除所有数据c1.delete_many({})if __name__ __main__:# add_data()# update_data()delete_data()
运行结果如下 接下来尝试做无参查询操作
# 引入三方模块
import pymongo# 创建连接(默认连接本机)
client pymongo.MongoClient()# 获取数据库实例(如果指定的数据库实例不存在就自动创建)
db1 client.Tsinghua
db2 client[PyMyMongo]# 获取集合(如果指定的集合不存在就自动创建)
c1 db1.user
c2 db2[user]
# c3中的数据较多方便做查询
c3 db1.person# 操作数据
def add_data():添加数据insert_one()用于向指定集合中插入一条数据insert_many()用于向指定集合中插入多条数据data1 {name:张三,age:20,score:89}data2 {name:李四,age:22,score:92}c1.insert_one(data1)c1.insert_many([data1,data2])def update_data():修改数据update_one用于修改第一个符合条件的文档update_many用于修改所有符合条件的文档# 指定要修改的数据args {name:张三}# c1.update_one(args,{$set:{age:30}})c1.update_many(args,{$set:{age:40}})def delete_data():删除数据delete_one()用于删除第一个符合条件的文档delete_many()用于删除所有符合条件的文档# 删除一条指定特征的数据# c1.delete_one({name:张三}}# 删除所有数据c1.delete_many({})def search_data():查询数据find()用于查询所有符合条件的文档find_one()用于查询第一个符合条件的文档resp_all c3.find()for resp in resp_all:print(resp)if __name__ __main__:# add_data()# update_data()# delete_data()search_data()
运行结果如下 接下来尝试操作有参查询
# 引入三方模块
import pymongo# 创建连接(默认连接本机)
client pymongo.MongoClient()# 获取数据库实例(如果指定的数据库实例不存在就自动创建)
db1 client.Tsinghua
db2 client[PyMyMongo]# 获取集合(如果指定的集合不存在就自动创建)
c1 db1.user
c2 db2[user]
# c3中的数据较多方便做查询
c3 db1.person# 操作数据
def add_data():添加数据insert_one()用于向指定集合中插入一条数据insert_many()用于向指定集合中插入多条数据data1 {name:张三,age:20,score:89}data2 {name:李四,age:22,score:92}c1.insert_one(data1)c1.insert_many([data1,data2])def update_data():修改数据update_one用于修改第一个符合条件的文档update_many用于修改所有符合条件的文档# 指定要修改的数据args {name:张三}# c1.update_one(args,{$set:{age:30}})c1.update_many(args,{$set:{age:40}})def delete_data():删除数据delete_one()用于删除第一个符合条件的文档delete_many()用于删除所有符合条件的文档# 删除一条指定特征的数据# c1.delete_one({name:张三}}# 删除所有数据c1.delete_many({})def search_data():查询数据find()用于查询所有符合条件的文档find_one()用于查询第一个符合条件的文档resp_all c3.find()for resp in resp_all:print(resp)def search_data_args():查询指定条件的数据rsp_all c3.find({age:{$gt:30}})for rsp in rsp_all:print(rsp)if __name__ __main__:# add_data()# update_data()# delete_data()# search_data()search_data_args()
运行结果如下 下面继续对search_data_args()函数做升级添加排序功能
# 引入三方模块
import pymongo# 创建连接(默认连接本机)
client pymongo.MongoClient()# 获取数据库实例(如果指定的数据库实例不存在就自动创建)
db1 client.Tsinghua
db2 client[PyMyMongo]# 获取集合(如果指定的集合不存在就自动创建)
c1 db1.user
c2 db2[user]
# c3中的数据较多方便做查询
c3 db1.person# 操作数据
def add_data():添加数据insert_one()用于向指定集合中插入一条数据insert_many()用于向指定集合中插入多条数据data1 {name:张三,age:20,score:89}data2 {name:李四,age:22,score:92}c1.insert_one(data1)c1.insert_many([data1,data2])def update_data():修改数据update_one用于修改第一个符合条件的文档update_many用于修改所有符合条件的文档# 指定要修改的数据args {name:张三}# c1.update_one(args,{$set:{age:30}})c1.update_many(args,{$set:{age:40}})def delete_data():删除数据delete_one()用于删除第一个符合条件的文档delete_many()用于删除所有符合条件的文档# 删除一条指定特征的数据# c1.delete_one({name:张三}}# 删除所有数据c1.delete_many({})def search_data():查询数据find()用于查询所有符合条件的文档find_one()用于查询第一个符合条件的文档resp_all c3.find()for resp in resp_all:print(resp)def search_data_args():查询指定条件的数据rsp_all c3.find({age:{$gt:30}})# 获取的游标对象需要通过遍历获取具体的元素for rsp in rsp_all:print(rsp)def search_data_args_sort():查询指定条件的数据并做降序处理rsp_all c3.find({age: {$gt: 30}}).sort(age,pymongo.DESCENDING)for rsp in rsp_all:print(rsp)if __name__ __main__:# add_data()# update_data()# delete_data()# search_data()# search_data_args()search_data_args_sort()
运行结果如下 下面尝试对排序后的结果做分页处理
# 引入三方模块
import pymongo# 创建连接(默认连接本机)
client pymongo.MongoClient()# 获取数据库实例(如果指定的数据库实例不存在就自动创建)
db1 client.Tsinghua
db2 client[PyMyMongo]# 获取集合(如果指定的集合不存在就自动创建)
c1 db1.user
c2 db2[user]
# c3中的数据较多方便做查询
c3 db1.person# 操作数据
def add_data():添加数据insert_one()用于向指定集合中插入一条数据insert_many()用于向指定集合中插入多条数据data1 {name:张三,age:20,score:89}data2 {name:李四,age:22,score:92}c1.insert_one(data1)c1.insert_many([data1,data2])def update_data():修改数据update_one用于修改第一个符合条件的文档update_many用于修改所有符合条件的文档# 指定要修改的数据args {name:张三}# c1.update_one(args,{$set:{age:30}})c1.update_many(args,{$set:{age:40}})def delete_data():删除数据delete_one()用于删除第一个符合条件的文档delete_many()用于删除所有符合条件的文档# 删除一条指定特征的数据# c1.delete_one({name:张三}}# 删除所有数据c1.delete_many({})def search_data():查询数据find()用于查询所有符合条件的文档find_one()用于查询第一个符合条件的文档resp_all c3.find()for resp in resp_all:print(resp)def search_data_args():查询指定条件的数据rsp_all c3.find({age:{$gt:30}})# 获取的游标对象需要通过遍历获取具体的元素for rsp in rsp_all:print(rsp)def search_data_args_sort():查询指定条件的数据并做降序处理rsp_all c3.find({age: {$gt: 30}}).sort(age,pymongo.DESCENDING)for rsp in rsp_all:print(rsp)def search_data_args_plus():查询指定条件的数据并做降序处理,打印时做分页处理rsp_all c3.find({age: {$gt: 30}}).sort(age, pymongo.DESCENDING).skip(4).limit(4)for rsp in rsp_all:print(rsp)if __name__ __main__:# add_data()# update_data()# delete_data()# search_data()# search_data_args()# search_data_args_sort()search_data_args_plus()
运行结果如下 最后演示pymongo如何获取集合中所有的数据条数
# 引入三方模块
import pymongo# 创建连接(默认连接本机)
client pymongo.MongoClient()# 获取数据库实例(如果指定的数据库实例不存在就自动创建)
db1 client.Tsinghua
db2 client[PyMyMongo]# 获取集合(如果指定的集合不存在就自动创建)
c1 db1.user
c2 db2[user]
# c3中的数据较多方便做查询
c3 db1.person# 操作数据
def add_data():添加数据insert_one()用于向指定集合中插入一条数据insert_many()用于向指定集合中插入多条数据data1 {name:张三,age:20,score:89}data2 {name:李四,age:22,score:92}c1.insert_one(data1)c1.insert_many([data1,data2])def update_data():修改数据update_one用于修改第一个符合条件的文档update_many用于修改所有符合条件的文档# 指定要修改的数据args {name:张三}# c1.update_one(args,{$set:{age:30}})c1.update_many(args,{$set:{age:40}})def delete_data():删除数据delete_one()用于删除第一个符合条件的文档delete_many()用于删除所有符合条件的文档# 删除一条指定特征的数据# c1.delete_one({name:张三}}# 删除所有数据c1.delete_many({})def search_data():查询数据find()用于查询所有符合条件的文档find_one()用于查询第一个符合条件的文档resp_all c3.find()for resp in resp_all:print(resp)def search_data_args():查询指定条件的数据rsp_all c3.find({age:{$gt:30}})# 获取的游标对象需要通过遍历获取具体的元素for rsp in rsp_all:print(rsp)def search_data_args_sort():查询指定条件的数据并做降序处理rsp_all c3.find({age: {$gt: 30}}).sort(age,pymongo.DESCENDING)for rsp in rsp_all:print(rsp)def search_data_args_plus():查询指定条件的数据并做降序处理,打印时做分页处理rsp_all c3.find({age: {$gt: 30}}).sort(age, pymongo.DESCENDING).skip(4).limit(4)for rsp in rsp_all:print(rsp)def count_data():获取当前集合中文档的总数# 注意count_documents()方法也可以统计指定条件的文档个数count c3.count_documents({})print(fc3中文档的总数为:{count})if __name__ __main__:# add_data()# update_data()# delete_data()# search_data()# search_data_args()# search_data_args_sort()# search_data_args_plus()count_data()
运行结果如下