# mongodbStudy
**Repository Path**: josnfei/mongodbStudy
## Basic Information
- **Project Name**: mongodbStudy
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2018-08-29
- **Last Updated**: 2021-12-29
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# MongoDB学习
## 第01节:认识和安装MongoDB
- 都知道MongoDB是非关系型数据库,要了解非关系型数据库就必须先了解关系型数据库,关系数据库,是建立在关系模型基础上的数据库。比较有名气的关系型数据库,比如Oracle、DB2、MSSQL、Mysql。
- 非关系数据库和关系型数据库的区别是什么?
+ 实质:非关系型数据库的实质:非关系型数据库产品是传统关系型数据库的功能阉割版,通过减少用不到或很少用的功能,来大幅度提高产品性能。
+ 价格:目前的非关系型数据库基本都是免费的,而比较有名气的关系型数据库都是收费的,比如:Oracle、DB2、MSSQL。MySql虽然是免费的,但是处理大型数据还是要提前作很多工作的。
+ 功能:实际开发中,很多业务需求,其实并不需要完整的关系型数据库功能,非关系型数据库的功能就足够使用了。这种情况下,使用性能更高、成本更低的非关系型数据库当然是更明智的选择。
- MongoDB简介:
```
MongoDB是一个基于分布式文件存储的数据库,由C++语言编写。目的是为WEB应用提供扩展的高性能的数据存储解决方案。MongoDB是一个介于关系型数据库和非关系型数据库之间的产品,是非关系型数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
```
- 安装MongoDB:
- MongoDB的安装分为Windows下的安装和Mac的安装(Liunx和Mac趋同)。这里我们只讲解windows的安装。
- 安装步骤:
+ 去官网下载MongoDB,https://www.mongodb.com/,在网站中找到Download按钮。下载会有点忙,国外的服务器,你懂的。
+ 下载后进行安装,安装没什么难度,但是对于新手建议选择默认安装,而不选择自己配置。等我们完全熟悉后再定制式配置。
+ 安装时如果有安全软件,会报一些拦截,一律允许就好,不允许会安装失败的。
+ 安装完成后,需要配置“环境变量”,目的是再命令行中直接使用,而不需要输入很长的路径了。(此步骤观看视频)
- 运行MongoDB服务端:
- (安装好MongoDB数据库后,我们需要启用服务端才能使用。启用服务的命令是:Mongod。)
+ 打开命令行:先打开运行(快捷键win+R),然后输入cmd后回车,就可以打开命令行工具。
+ 执行mongod:在命令中直接输入mongod,但是你会发现服务并没有启动,报了一个exception,服务停止了。
+ 新建文件夹:出现上边的错误,是因为我们没有简历Mongodb需要的文件夹,一般是安装盘的根目录,建立data/db,这两个文件夹。
+ 运行mongod:这时候服务就可以开启了,链接默认端口是27017。
- 链接服务:
```
服务端开启后,我们可以使用命令行来链接服务端,链接命令是mongo。重新打开一个命令行工具,然后输入mongo命令。也许你在链接时会报几个warning(警告),我们先不用管它,以后我们再慢慢学习。
查看存在数据库命令:show dbs
查看数据库版本命令:db.version()
如果这两条命令都可以正常的显示出结果,证明我们的MongoDB数据库已经安装成功了,以后我们就可以愉快的开始学习了。想学习的小伙伴学完后自己动手安装一下吧,只有自己动手才能真正学会
```
## 第02节:Mongo基本命令-1
接下来的几节直接上手Mongo命令,先让小伙伴对MongoDB的基本命令会使用,算是快速上手。快速上手后,我们再用以后的课程把这些命令细化和升级,形成一套完整的MongoDB知识体系。小伙伴们不要着急,让我们开始学习吧。
mongo shell 如果以前接触过数据库一定知道每个数据库都有自己独特的命令,MSSQL和MYsql用的都是Sql命令,MongoDB的操作命令就是前端最熟悉的JavaScript命令。看到这里作为前端你一定会小激动一下,这对前端来说那是极好的。
先来一个常用的赋值和输出命令,熟悉一下。(操作前你需要打开Mongo服务器和链接到服务器-也就是我们上节课讲的mongod命令和mongo命令)在命令行中输入以下代码。
var x='Hello World'
print(x)
需要注意的是这里的输出不再使用console.log(‘巴拉巴拉’),而是使用print(‘巴拉巴拉’),这个稍有区别。
还可以定义函数:
function jspang(){
return 'JSPang';
}
学到这里,我们用的都是JavaScript的语法,这些我们可以信手拈来,非常容易
- MongoDB的存储结构
以前我们的关系型数据库的数据结构都是顶层是库,库下面是表,表下面是数据。但是MongoDB有所不同,库下面是集合,集合下面是文件,可以看下面这张图进行了解一下。
在学习中我们可以对比记忆,这样才能更好的了解这些名词,其实数据表就是集合,数据行就是文件,当然这只是为了记忆,实质还是有区别的。
- 基础Shell命令:
- 了解存储结构后,就可以开始学习我们的基础Shell命令了,因为这些命令比较基础,我会以列表形式展现,具体使用方法可以到视频中进行观看。
+ show dbs :显示已有数据库,如果你刚安装好,会默认有local、admin(config),这是MongoDB的默认数据库,我们在新建库时是不允许起这些名称的。
+ use admin: 进入数据,也可以理解成为使用数据库。成功会显示:switched to db admin。
+ show collections: 显示数据库中的集合(关系型中叫表,我们要逐渐熟悉)。
+ db:显示当前位置,也就是你当前使用的数据库名称,这个命令算是最常用的,因为你在作任何操作的时候都要先查看一下自己所在的库,以免造成操作错误。
- 总结:
这节课的学习已经让我们进入了MongoDB的世界,你会感觉使用起来还是比较简单的,都是些基本的命令,敲入回车就可以使用,但是大家还是要进行多联系。这节课的重点是要转变以前数据库存储结构的思想,掌握MongoDB的存储结构
## 第03节:Mongo基本命令-2
这节课继续学习MongoDB的基础命令,上节课我们学了一些最简单的查看命令,比如查看数据库,查看集合,显示当前位置。这节课我们开始真实的操作一下数据,学会基本的数据增删改查。直接看视频开始学习吧。
- 数据操作基础命令:
+ use db(建立数据库):use不仅可以进入一个数据库,如果你敲入的库不存在,它还可以帮你建立一个库。但是在没有集合前,它还是默认为空。
+ db.集合.insert( ):新建数据集合和插入文件(数据),当集合没有时,这时候就可以新建一个集合,并向里边插入数据。Demo:db.user.insert({“name”:”jspang”})
+ db.集合.find( ):查询所有数据,这条命令会列出集合下的所有数据,可以看到MongoDB是自动给我们加入了索引值的。Demo:db.user.find()
+ db.集合.findOne( ):查询第一个文件数据,这里需要注意的,所有MongoDB的组合单词都使用首字母小写的驼峰式写法。
+ db.集合.update({查询},{修改}):修改文件数据,第一个是查询条件,第二个是要修改成的值。这里注意的是可以多加文件数据项的,比如下面的例子。
- db.jspang.update({"name":"jspang"},{"name":"jspang","age":"32"})
+ db.集合.remove(条件):删除文件数据,注意的是要跟一个条件。Demo:db.user.remove({“name”:”jspang”})
+ db.集合.drop( ):删除整个集合,这个在实际工作中一定要谨慎使用,如果是程序,一定要二次确认。
+ db.dropDatabase( ):删除整个数据库,在删除库时,一定要先进入数据库,然后再删除。实际工作中这个基本不用,实际工作可定需要保留数据和痕迹的。
## 第04节:用js文件写mongo命令
在命令行中写mongo的命令(shell)实在是太麻烦了(反正技术胖是无法忍受windows系统的这种命令行的),急需一种更好的方式来进行工作,这节课我们就学一下用JS文件来写shell命令和执行。在JS里写mongo的Shell命令大部分是相同的,只有小部分不一样。
把命令写入JS中: 现在模拟一个用户登录日志表的信息,用JS进行编写。新在一个新建的目录下,比如D:/mongoShell/,新建一个goTask.js文件。文件内容如下:
- goTask.js文件
```javascript
var userName='Dfei'; //用户名
var timeStamp=Date.parse(new Date()); //登录的时间戳
var jsonDdatabase={'loginUser':userName,'loginTime':timeStamp}; //组成的json字符串要插入mongodb里面的数据
var db=connect('log'); //链接数据库--> log实际是数据库名 相当于shell里面的use log 最后,这里声明不要用let,否则会报错
db.login.insert(jsonDdatabase); //插入数据
print('[demo]log print success'); //没有错误显示成功
```
如果上边这个基础的代码你看起来还不是那么容易,那我建议你先停下这门课的学习,去学一下JS的基础知识,只有基础打牢了,学习起来才会快速。
- 执行JS文件
写好了JS文件,需要执行起来,看一下文件是否存在问题,能否顺利的插入数据到MongoDB中。
执行其实很简单,只要使用mongo xxx.js(xxx就是我们写的goTask.js文件)。
mongo goTask.js
然后我们可以在命令行看到已经执行成功,可以到终端中进行查看插入结果。
- 总结:这节课很好的解决了在终端中写命令行的难题,虽然大部分Shell和在命令行中写法一样,但是也稍有不同,希望小伙伴们可以轻松掌握。
## 第05节:批量插入的正确方法
前4节课,我们都是简单讲解了MongoDB的使用方法,目的是快速入门。从这节课开始,我们要详细深入的讲解MongoDB的各项操作,难度也开始逐渐提高。需要提示如果前边的课程还没有联系熟练,那先练习一下,否则接下来学习会稍有困难。
- 在操作数据库时要注意两个能力:
+ 第一个是快速存储能力。
+ 第二个是方便迅速查询能力。
- 批量插入:
批量数据插入是以数组的方式进行的(如果写错,可以3个回车可以切出来)。我们现在命令行中敲入下面的代码,我们可以看到数据顺利插入了。
```javascript
db.test.insert([
{"_id":1},
{"_id":2},
{"_id":3}
])
```
老版本MongoDB(3.2以前的版本基本都需要)是需要在Insert前加一个batch单词的,如下代码。
```javascript
db.test.batchInsert([
{"_id":1},
{"_id":2},
{"_id":3}
])
```
注意一次插入不要超过48M,向.zip和大图片什么的尽量用静态存储,MongoDB存储静态路径就好,这也算是一个规则。
- 批量插入性能测试
刚学了批量插入,那是循环插入快?还是批量插入快那?在一般人的认知里肯定是批量插入更快(其实这毋庸置疑),但我们要拿出极客精神,探个究竟,试着写一个小Shell,来验证一下结果。
- 先写一个循环插入方法:
```javascript
var startTime = (new Date()).getTime(); //得到开始时间
var db = connect('log'); //链接数据库
//开始循环
for(let i=0;i<1000;i++){
db.test.insert({num:i});
}
var runTime = (new Date()).getTime()-startTime;//计算时间差
print ('This run this is:'+runTime+'ms');//打印出来
```
我测试的时间507ms,这个速度虽然和电脑性能有关,但还是不太理想,1000条数据用了将近半秒,组长会发飙的。
- 批量插入代码:
```javascript
var startTime = (new Date()).getTime();
var db = connect('log');
var tempArray = [] //声明一个数组
for(let i=0;i<1000;i++){ //循环向数组中放入值
tempArray.push({num:i});
}
db.test.insert(tempArray) //批量一次插入
var runTime = (new Date()).getTime()-startTime;
print ('This run this is:'+runTime+'ms');
```
这次用了17ms,性能远远超过循环插入。
- 总结:在工作中一定要照顾数据库性能,这也是你水平的提现,一个技术会了很简单,但是要作精通不那么简单。学完这节,记得在工作中如果在循环插入和批量插入举起不定,那就选批量插入吧,它会给我们更优的性能体验。
- 第五节代码
```javascript
// 循环插入和批量插入性能对比 批量插入更快
// 循环插入
// var startTime=(new Date()).getTime();
// var db=connect('log'); //链接数据库
// for(var i=0;i<1000;i++){
// db.mytest.insert({num:i});
// }
// var runtime = (new Date()).getTime() - startTime;
// print('runingTime'+runtime+ 'ms' ); //控制台打印出来 //960ms
// 批量插入
var startTime=(new Date()).getTime();
var db=connect('log'); //链接数据库
var arr=[];
for(var i=0;i<1000;i++){
arr.push({num:i});
}
db.pitest.insert(arr); //批量一次插入
var runtime=(new Date()).getTime()-startTime;
print('runingTimg' + runtime + 'MS'); //157MS
```
## 第06节:修改:Update常见错误
这节课开始我们要说一说Update的详细操作,我们先来看一下常见错误,我们知道了困难或者说问题在哪里,我们再提出解决方案。这节课我会先演示一些错误的Update方法,然后再说正确的方法。希望不要误导小伙伴。
- 第6节代码
```javascript
// demo06.js
var workmate1 = {
name: 'JSPang',
age: 33,
sex: 1,
job: '前端',
skill: {
skillOne: 'HTML+CSS',
SkillTwo: 'JavaScript',
SkillThree: 'PHP'
},
regeditTime: new Date()
}
var workmate2 = {
name: 'ShengLei',
age: 30,
sex: 1,
job: 'JAVA后端',
skill: {
skillOne: 'HTML+CSS',
SkillTwo: 'J2EE',
SkillThree: 'PPT'
},
regeditTime: new Date()
}
var workmate3 = {
name: 'MinJie',
age: 20,
sex: 1,
job: 'UI设计',
skill: {
skillOne: 'PhotoShop',
SkillTwo: 'UI',
SkillThree: 'Word+Excel+PPT'
},
regeditTime: new Date()
}
var db = connect('company')
var workmateArray = [workmate1, workmate2, workmate3]
db.workmate.insert(workmateArray)
print('[SUCCESS]: The data was inserted successfully.');
```
```javascript
// demo061.js 错误的做法
// 错误的修改数据的方法
var db=connect('company');
db.workmate.update({ 'name': 'Minjie' }, { 'sex': 0 }); //会把name:'Minjie'的这条数据给覆盖
print('错误的修改方法执行成功')
```
```javascript
// demo062.js正确的做法
// 正确的做法
// 写一个一样的,然后用进去覆盖,这种方法比较麻烦,第七节学习update修改器
var db = connect('company')
var workmate3 = {
name: 'MinJie',
age: 20,
sex: 0,
job: 'UI设计',
skill: {
skillOne: 'PhotoShop',
SkillTwo: 'UI',
SkillThree: 'Word+Excel+PPT'
},
regeditTime: new Date()
}
db.workmate.update({ name: 'MinJie' }, workmate3)
print('[update]: The data was updated successfully');
```
## 第07节:修改:初识update修改器
上节课的修改用起来实在是不够优雅,这是我们一个伟大的前端不能接受的,所以我们要学习新知识update修改器,来解决这个问题。update修改器可以帮助我们快速和简单的修改数据,让我们的操作更简单方便
- 直接上代码,看注释
```javascript
// 数据库company 集合workmate 文件内容是demo06.js的文件内容
var db=connect('company'); //链接数据库
// $set修改器
// 用来修改一个指定的键值(key),这时候我们要修改上节课的sex和age就非常方便了,只要一句话就可以搞定。
// db.workmate.update({'name':'MinJie'},{$set:{sex:2,age:21}});
// $set 也可以修改嵌套内容(内嵌文档)
// 比如现在的UI的技能发生了变化,说她不会作PPT而是word作的很好,需要进行修改。这时候你会发现skill数据是内嵌的,这时候我们可以属性的形式进行修改,skill.skillThree。具体看下面的代码
// db.workmate.update({name:'MinJie'},{$set:{'skill.SkillThree':'word12'}}) //内嵌里面的键值对,注意大小写,存的是大写,改的时候写也是要大写,否则,就会变成添加
// $unset用于将key和对应值删除
// 它的作用其实就是删除一个key值和键。一般女孩子都是不希望看到自己的年龄的,所以要求我们把年龄删除。这时候我们就可以使用$unset的形式。
// db.workmate.update({ 'name': 'MinJie' }, { $unset: {'skill.skilltree':''}}) //也可以改内嵌的内容, 赋值为空,就是删除
// $inc对数字进行计算
// 它是对value值的修改,但是修改的必须是数字,字符串是不起效果的。我们现在要对MiJie的年龄减去2岁,就可以直接用$inc来操作。
// db.workmate.update({'name':'MinJie'},{$inc:{age:-2}})
// multi选项 全局,所有的都改,当然,条件也必须是全局{} 只有ture(全部修改) 和false只修改一个(默认值) 两个值
// 现在领导说了,你要把每个人的爱好也加入进来,但是如果你直接写会只加一个,比如下面这种形式。
// db.workmate.update({}, { $set: { interset: [] } })
// 这时候你用db.workmate.find()查找,你会发现只改变了第一个数据,其他两条没有改变。这时候我们想改变就要用到multi选项。
// db.workmate.update({}, { $set: { interset: [] } }, { multi: true })
// 这时候每个数据都发生了改变,multi是有ture和false两个值,true代表全部修改,false代表只修改一个(默认值)
// upsert选项
// upsert是在找不到值的情况下,直接插入这条数据。比如我们这时候又来了一个新同事xiaoWang,我们这时候修改他的信息,age设置成20岁,但集合中并没有这条数据。这时候可以使用upsert选项直接添加。
// db.workmate.update({ name: 'xiaoWang' }, { $set: { age: 20 } }, { upsert: true})
// upsert也有两个值:true代表没有就添加,false代表没有不添加(默认值)。
// 总结:这节课的内容非常多,主要学习了update修改器有关的一些东西。一定要课下多练习几遍,否则很快就会忘记的。
// 个人练习
// 1. 想法,把每个人的年龄都删除
// db.workmate.update({},{$unset:{'age':''}},{multi:true});
// 2. 给JSPang单独加年龄
// db.workmate.update({ name:'JSPang'},{$set:{age:21}})
// 3.给所有人加年龄,并且为33岁,如果已经有年龄的了,则用他之前的,否则添加年龄这个信息 这个暂时实现不了,会全部改为33,不知道为何
// db.workmate.update({}, { $set: { age: 33 } },true,true) //也可以这样用,第一个true代表upsert,第二个是multi
// db.workmate.update({}, { $set: { age: 33 } }, { upsert: true,multi: true })
// 菜鸟教程 update的用法
// db.collection.update(
// < query >,
// ,
// {
// upsert: ,
// multi: ,
// writeConcern:
// }
// )
print('修改成功')
```
### 注意:
- 如果是在mongo命令行下,而且是在当前JS文件目录下,可以直接load(./文件名.js) 直接运行数据库命令,自动跑这个JS文件了
## 第08节:修改:update数组修改器
已经会了一些基础的修改器,这节课我们主要学习一下数组修改器的操作,当然也可以修改内嵌文档,也就是对象形式的数据。让我们努力学习吧。
- $push追加数组/内嵌文档值
- $push的功能是追加数组中的值,但我们也经常用它操作内嵌稳文档,就是{}对象型的值。先看一个追加数组值的方式,比如我们要给小王加上一个爱好(interset)为画画(draw):
```javascript
// 本地数据为demo08
var db=connect('demo08'); //链接数据库
// $push追加数组/内嵌文档值
// $push的功能是追加 "数组" 中的值,但我们也经常用它操作内嵌稳文档,就是{}对象型的值。先看一个追加数组值的方式,比如我们要给小王加上一个爱好(interset)为画画(draw):
// db.workmate.update({ 'name': 'xiaoWang' }, { $push: { aihao: 'draw' } }); //加进来的是一个数组 { "_id" : ObjectId("5b8aa095283e6b5608563aae"), "name" : "xiaoWang", "age" : 20, "aihao" : [ "draw" ] }
// 当然$push修饰符还可以为 "内嵌文档" 增加值,比如我们现在要给我们的UI,增加一项新的技能skillFour为draw,这时候我们可以操作为:
// UI原本数据为{ "_id" : ObjectId("5b8a9fc8b98908f8cdac7476"), "name" : "MinJie", "age" : 20, "sex" : 1, "job" : "UI设计", "skill" : { "skillOne" : "PhotoShop", "SkillTwo" : "UI", "SkillThree" : "Word+Excel+PPT" }, "regeditTime" : ISODate("2018-09-01T14:18:48.663Z") }
// db.workmate.update({ 'name':'MinJie'},{$push:{'skill.SkillFour':'draw'}})
// 添加后,UI数据为: { "_id" : ObjectId("5b8a9fc8b98908f8cdac7476"), "name" : "MinJie", "age" : 20, "sex" : 1, "job" : "UI设计", "skill" : { "skillOne" : "PhotoShop", "SkillTwo" : "UI", "SkillThree" : "Word+Excel+PPT", "SkillFour" : [ "draw" ] }, "regeditTime" : ISODate("2018-09-01T14:18:48.663Z") }
// $push修饰符在工作中是最常用的,因为我们的数据一般都会涉及数组和内嵌文档的操作,一定要掌握。
// $ne查找是否存在
// 它主要的作用是,检查一个值是否存在,如果不存在再执行操作,存在就不执行,这个很容易弄反,记得我刚学的时候就经常弄反这个修改器的作用,给自己增加了很多坑。
// 例子:如果xiaoWang的爱好(interest)里没有palyGame这个值,我们就加入Game这个爱好。
// 原本值为{ "_id" : ObjectId("5b8aa095283e6b5608563aae"), "name" : "xiaoWang", "age" : 20, "aihao" : [ "draw" ] }
// db.workmate.update({'name':'xiaoWang','aihao':{$ne:'palyGame'}},{$push:{'aihao':'Game'}});
//改后值为: { "_id" : ObjectId("5b8aa095283e6b5608563aae"), "name" : "xiaoWang", "age" : 20, "aihao" : [ "draw", "Game" ] }
// 总结:没有则修改,有则不修改。
// $addToSet 升级版的$ne 注意$addToSet是驼峰命名,别打错了,打错执行不会报错,但是实际没改成功
// 它是$ne的升级版本(查找是否存在,不存在就push上去),操作起来更直观和方便,所以再工作中这个要比$en用的多。
// 例子:我们现在要查看小王(xiaoWang)兴趣(interest)中有没有阅读(readBook)这项,没有则加入读书(readBook)的兴趣.
// 原本值为:{ "_id" : ObjectId("5b8aa095283e6b5608563aae"), "name" : "xiaoWang", "age" : 20, "aihao" : [ "draw", "Game" ] }
// db.workmate.update({name:'xiaoWang'},{$addToSet:{'aihao':'readbook'}})
// 改后值为: { "_id" : ObjectId("5b8aa095283e6b5608563aae"), "name" : "xiaoWang", "age" : 20, "aihao" : [ "draw", "Game", "readbook" ] }
// $each 批量追加
// 它可以传入一个数组,一次增加多个值进去,相当于批量操作,性能同样比循环操作要好很多,这个是需要我们注意的,工作中也要先组合成数组,然后用批量的形式进行操作。
// 例子:我们现在要给xiaoWang, 一次加入三个爱好,唱歌(Sing),跳舞(Dance),编码(Code)。
// 原本值为: { "_id" : ObjectId("5b8aa095283e6b5608563aae"), "name" : "xiaoWang", "age" : 20, "aihao" : [ "draw", "Game", "readbook" ] }
// var newInterset = ["Sing", "Dance", "Code"];
// db.workmate.update({ 'name': 'xiaoWang' }, { $addToSet: { 'aihao': { $each: newInterset}}})
// 改后的值为: { "_id" : ObjectId("5b8aa095283e6b5608563aae"), "name" : "xiaoWang", "age" : 20, "aihao" : [ "draw", "Game", "readbook", "Sing", "Dance", "Code" ] }
// $pop 删除数组值
// $pop只删除一次,并不是删除所有数组中的值。而且它有两个选项,一个是1和-1。
// 1:从数组末端进行删除
// -1:从数组开端进行删除
// 例子:现在要删除xiaoWang的编码爱好(code)。
// 原本值为:{ "_id" : ObjectId("5b8aa095283e6b5608563aae"), "name" : "xiaoWang", "age" : 20, "aihao" : [ "draw", "Game", "readbook", "Sing", "Dance", "Code" ] }
// db.workmate.update({name:'xiaoWang'},{$pop:{aihao:1}})
// 改后的值为: { "_id" : ObjectId("5b8aa095283e6b5608563aae"), "name" : "xiaoWang", "age" : 20, "aihao" : [ "draw", "Game", "readbook", "Sing", "Dance" ] }
// 数组定位修改
// 有时候只知道修改数组的第几位,但并不知道是什么,这时候我们可以使用interest.int 的形式。
// 例子,比如我们现在要修改xiaoWang的第三个兴趣为编码(Code),注意这里的计数是从0开始的。
// 原本值为:{ "_id" : ObjectId("5b8aa095283e6b5608563aae"), "name" : "xiaoWang", "age" : 20, "aihao" : [ "draw", "Game", "readbook", "Sing", "Dance" ] }
// db.workmate.update({name:'xiaoWang'},{$set:{'aihao.2':'Code'}})
// 改后的值为: { "_id" : ObjectId("5b8aa095283e6b5608563aae"), "name" : "xiaoWang", "age" : 20, "aihao" : [ "draw", "Game", "Code", "Sing", "Dance" ] }
// 总结:这节课主要讲了于数组和内嵌文档有关的update修改器,内容很多,都需要不断熟练记忆。当然如果你记不住,你至少记住这个博客网址,因为技术胖把笔记已经给你整理好了。
// 个人练习
// 1. xiaoWang这个用户,把它第二个爱好删除了
// 原本数据为: { "_id" : ObjectId("5b8aa095283e6b5608563aae"), "name" : "xiaoWang", "age" : 20, "aihao" : [ "draw", "Game", "Code", "Sing", "Dance" ] }
db.workmate.update({name:'xiaoWang'},{$unset:{'aihao.1':''}}) //只变成了null,并没能删除
// 改后值为: { "_id" : ObjectId("5b8aa095283e6b5608563aae"), "name" : "xiaoWang", "age" : 20, "aihao" : [ "draw", null, "Code", "Sing", "Dance" ] }
print('执行成功');
```
## 第09节:修改:状态返回与安全
在操作数据库时,对数据的修改是需要有足够的安全措施的,其实在实际工作中,我们用db.collections.update的时候不多,在修改时我们都会用findAndModify,它可以给我们返回来一些必要的参数,让我们对修改多了很多控制力,控制力的加强也就是对安全的强化能力加强了。
```javascript
var db = connect('demo08'); //链接数据库
// 第09节:修改:状态返回与安全
/*
在操作数据库时,对数据的修改是需要有足够的安全措施的,其实在实际工作中,我们用db.collections.update的时候不多,
在修改时我们都会用findAndModify,它可以给我们返回来一些必要的参数,让我们对修改多了很多控制力,控制力的加强也就
是对安全的强化能力加强了。
*/
// 应答式写入:
/*
在动手学习代码之前,我们先来了解一个概念:应答式写入。在以前的文章中,我们的操作都是非应答式写入,就是在操作完数据
库后,它并没有给我们任何的回应和返回值,而是我们自己安慰自己写了一句话(print(‘[update]:The data was updated su
ccessfully’);)。这在工作中是不允许的,因为根本不能提现我们修改的结果。
应答式写入就会给我们直接返回结果(报表),结果里边的包含项会很多,这样我们就可以很好的进行程序的控制和安全机制的处理。
有点像前端调用后端接口,无论作什么,后端都要给我一些状态字一样。
*/
// db.runCommand():
/*
它是数据库运行命令的执行器,执行命令首选就要使用它,因为它在Shell和驱动程序间提供了一致的接口。(几乎操作数据库的所有
操作,都可以使用runCommand来执行)现在我们试着用runCommand来修改数据库,看看结果和直接用db.collections.update有什
么不同。
*/
// db.workmate.update({ sex: 1 }, { $set: { money: 1000 } }, false, true); //false:第一句末尾的false是upsert的简写,代表没有此条数据时不增加; true:true是multi的简写,代表修改所有,这两个我们在前边课程已经学过。
// var resultMessage = db.runCommand({ getLastError: 1 }); //getLastError:1 :表示返回功能错误,这里的参数很多,如果有兴趣请自行查找学习,这里不作过多介绍。
// printjson(resultMessage); //printjson:表示以json对象的格式输出到控制台。
/*
执行后,db.workmate.find()查了结果 疑问: 明明upsert为false,而且sex为1的,都没有money这个属性,为什么最后还加成功上去,不是upsert为false就不加吗
{ "_id" : ObjectId("5b8a9fc8b98908f8cdac7474"), "name" : "JSPang", "age" : 33, "sex" : 1, "job" : "前端", "skill" : { "skillOne" : "HTML+CSS", "SkillTwo" : "JavaScript", "SkillThree" : "PHP" }, "regeditTime" : ISODate("2018-09-01T14:18:48.663Z"), "money" : 1000 }
{ "_id" : ObjectId("5b8a9fc8b98908f8cdac7475"), "name" : "ShengLei", "age" : 30, "sex" : 1, "job" : "JAVA后端", "skill" : { "skillOne" : "HTML+CSS", "SkillTwo" : "J2EE", "SkillThree" : "PPT" }, "regeditTime" : ISODate("2018-09-01T14:18:48.663Z"), "money" : 1000 }
{ "_id" : ObjectId("5b8a9fc8b98908f8cdac7476"), "name" : "MinJie", "age" : 20, "sex" : 0, "job" : "UI设计", "skill" : { "skillOne" : "PhotoShop", "SkillTwo" : "UI", "SkillThree" : "Word+Excel+PPT", "SkillFour" : [ "draw" ] }, "regeditTime" : ISODate("2018-09-01T14:18:48.663Z") }
{ "_id" : ObjectId("5b8aa095283e6b5608563aae"), "name" : "xiaoWang", "age" : 20, "aihao" : [ "draw", null, "Code", "Sing", "Dance" ] }
*/
/*
上边的代码,我们修改了所有男士的数据,每个人增加了1000元钱(money),然后用db.runCommand()执行,可以看到执行结果在控制
台返回了。
*/
/*
connecting to: mongodb://127.0.0.1:27017/demo08
MongoDB server version: 3.4.0
{
"connectionId" : 17,
"updatedExisting" : true,
"n" : 2,
"syncMillis" : 0,
"writtenTo" : null,
"err" : null,
"ok" : 1
}
true
*/
/*
false:第一句末尾的false是upsert的简写,代表没有此条数据时不增加;
true:true是multi的简写,代表修改所有,这两个我们在前边课程已经学过。
getLastError:1 :表示返回功能错误,这里的参数很多,如果有兴趣请自行查找学习,这里不作过多介绍。
printjson:表示以json对象的格式输出到控制台。
*/
// db.listCommands( ):查看所有的Commad命令,内容很多,本套课程只讲解工作中经常使用的内容。
// 比如我们要查看是否和数据库链接成功了,就可以使用Command命令。
// db.runCommand({ ping: 1 })
// 返回ok:1就代表链接正常。
// findAndModify:
// 从名字上就可以看出,findAndModify是查找并修改的意思。配置它可以在修改后给我们返回修改的结果。
// 我们先看下面的代码:
var myModify={
findAndModify: 'workmate', //集合
query: { name: 'xiaoWang' }, //需要查询的条件/文档
update:{$set:{age:56}},
new: true //更新完成,需要查看结果,如果为false不进行查看结果
}
var resultMessage = db.runCommand(myModify);
printjson(resultMessage)
// 执行之后放回的结果
/*
{
"lastErrorObject" : {
"updatedExisting" : true,
"n" : 1
},
"value" : {
"_id" : ObjectId("5b8aa095283e6b5608563aae"),
"name" : "xiaoWang",
"age" : 56,
"aihao" : [
"draw",
null,
"Code",
"Sing",
"Dance"
]
},
"ok" : 1
}
true
*/
// findAndModify的性能是没有直接使用db.collections.update的性能好,但是在实际工作中都是使用它,毕竟要商用的程序安全性还是比较重要的。
// findAndModify属性值:
/*
query:需要查询的条件/文档
sort: 进行排序
remove:[boolean]是否删除查找到的文档,值填写true,可以删除。
new:[boolean]返回更新前的文档还是更新后的文档。
fields:需要返回的字段
upsert:没有这个值是否增加。
*/
// 总结:这节课讲了一些跟安全有关的操作,但这不是全部,我们随着课程的深入还会继续学习更多的知识。工作中尽量使用findAndModify来进行更新数据,这样会更安全和直观,这点性能的损失是值得的。
```
## 第10节:查询:find的不等修饰符
MongoDB的查找操作我们会分几节课来讲,因为内容还是比较多的,而且在开发中查找是应用最多的操作,几乎每个模块都会用到,所以查找的部分将是本套课的重中之重。这节课我们先来看看简单的查询条件,也了解一下find基础用法。如果你以前操作过关系型数据库,比如MySql,你会对>大于),<(小于),=(等于)这些东西很熟悉,但是非关系型数据库不能直接使用这些符号,稍有区别。
```javascript
// 第10节:查询:find的不等修饰符
/*
MongoDB的查找操作我们会分几节课来讲,因为内容还是比较多的,而且在开发中查找是应用最多的操作,几乎每个模块都会用到,
所以查找的部分将是本套课的重中之重。这节课我们先来看看简单的查询条件,也了解一下find基础用法。如果你以前操作过关系
型数据库,比如MySql,你会对>大于),<(小于),=(等于)这些东西很熟悉,但是非关系型数据库不能直接使用这些符号,稍有区别。
*/
// 构造数据:
/*
我们需要构造更多的数据到集合中,这样我们才能很好的讲解查询条件,下面代码你可以直接复制进行添加。当然你也可以自己随
意加一些数据到集合中,只要方便我们学习就可以了。
*/
var workmate1 = {
name: 'JSPang',
age: 33,
sex: 1,
job: '前端',
skill: {
skillOne: 'HTML+CSS',
skillTwo: 'JavaScript',
skillThree: 'PHP'
},
regeditTime: new Date(),
interest: []
}
var workmate2 = {
name: 'ShengLei',
age: 31,
sex: 1,
job: 'JAVA后端',
skill: {
skillOne: 'HTML+CSS',
skillTwo: 'J2EE',
skillThree: 'PPT'
},
regeditTime: new Date(),
interest: []
}
var workmate3 = {
name: 'MinJie',
age: 18,
sex: 0,
job: 'UI',
skill: {
skillOne: 'PhotoShop',
skillTwo: 'UI',
skillThree: 'PPT'
},
regeditTime: new Date(),
interest: []
}
var workmate4 = {
name: 'XiaoWang',
age: 25,
sex: 1,
job: 'UI',
skill: {
skillOne: 'PhotoShop',
skillTwo: 'UI',
skillThree: 'PPT'
},
regeditTime: new Date(),
interest: []
}
var workmate5 = {
name: 'LiangPeng',
age: 28,
sex: 1,
job: '前端',
skill: {
skillOne: 'HTML+CSS',
skillTwo: 'JavaScript',
},
regeditTime: new Date(),
interest: []
}
var workmate6 = {
name: 'HouFei',
age: 25,
sex: 0,
job: '前端',
skill: {
skillOne: 'HTML+CSS',
skillTwo: 'JavaScript',
},
regeditTime: new Date(),
interest: []
}
var workmate7 = {
name: 'LiuYan',
age: 35,
sex: 0,
job: '美工',
skill: {
skillOne: 'PhotoShop',
skillTwo: 'CAD',
},
regeditTime: new Date(),
interest: []
}
var workmate8 = {
name: 'DingLu',
age: 20,
sex: 0,
job: '美工',
skill: {
skillOne: 'PhotoShop',
skillTwo: 'CAD',
},
regeditTime: new Date(),
interest: []
}
var workmate9 = {
name: 'JiaPeng',
age: 29,
sex: 1,
job: '前端',
skill: {
skillOne: 'HTML+CSS',
skillTwo: 'JavaScript',
skillThree: 'PHP'
},
regeditTime: new Date(),
interest: []
}
var workmate10 = {
name: 'LiJia',
age: 26,
sex: 0,
job: '前端',
skill: {
skillOne: 'HTML+CSS',
skillTwo: 'JavaScript',
skillThree: 'PHP'
},
regeditTime: new Date(),
interest: []
}
var db = connect('demo10');
var workmateArray = [workmate1, workmate2, workmate3, workmate4, workmate5, workmate6, workmate7, workmate8, workmate9, workmate10];
db.workmate.insert(workmateArray);
print('[SUCCESS]:The data was inserted successfully');
// 简单查找:
// 比如我们现在要查找数据中技能一会HTML+CSS的所有人。那我们直接进行查找加条件就可以了。
// db.workmate.find({"skill.skillOne":"HTML+CSS"})
// 这时候我们不能使用load来载入了,以后我会给大家讲使用的方法,这里先用比较笨的方法,使用粘贴复制的方法执行。
/*
结果:
{ "_id" : ObjectId("5b8e908d081ab44f912d4485"), "name" : "JSPang", "age" : 33, "sex" : 1, "job" : "前端", "skill" : { "skillOne" : "HTML+CSS", "skillTwo" : "JavaScript", "skillThree" : "PHP" }, "regeditTime" : ISODate("2018-09-04T14:02:53.401Z"), "interest" : [ ] }
{ "_id" : ObjectId("5b8e908d081ab44f912d4486"), "name" : "ShengLei", "age" : 31, "sex" : 1, "job" : "JAVA后端", "skill" : { "skillOne" : "HTML+CSS", "skillTwo" : "J2EE", "skillThree" : "PPT" }, "regeditTime" : ISODate("2018-09-04T14:02:53.401Z"), "interest" : [ ] }
{ "_id" : ObjectId("5b8e908d081ab44f912d4489"), "name" : "LiangPeng", "age" : 28, "sex" : 1, "job" : "前端", "skill" : { "skillOne" : "HTML+CSS", "skillTwo" : "JavaScript" }, "regeditTime" : ISODate("2018-09-04T14:02:53.401Z"), "interest" : [ ] }
{ "_id" : ObjectId("5b8e908d081ab44f912d448a"), "name" : "HouFei", "age" : 25, "sex" : 0, "job" : "前端", "skill" : { "skillOne" : "HTML+CSS", "skillTwo" : "JavaScript" }, "regeditTime" : ISODate("2018-09-04T14:02:53.401Z"), "interest" : [ ] }
{ "_id" : ObjectId("5b8e908d081ab44f912d448d"), "name" : "JiaPeng", "age" : 29, "sex" : 1, "job" : "前端", "skill" : { "skillOne" : "HTML+CSS", "skillTwo" : "JavaScript", "skillThree" : "PHP" }, "regeditTime" : ISODate("2018-09-04T14:02:53.401Z"), "interest" : [ ] }
{ "_id" : ObjectId("5b8e908d081ab44f912d448e"), "name" : "LiJia", "age" : 26, "sex" : 0, "job" : "前端", "skill" : { "skillOne" : "HTML+CSS", "skillTwo"
: "JavaScript", "skillThree" : "PHP" }, "regeditTime" : ISODate("2018-09-04T14:02:53.401Z"), "interest" : [ ] }
*/
// 筛选字段
/*
现在返回来的数据项太多,太乱,有时候我们的程序并不需要这么多选项。比如我们只需要姓名和技能就可以了。这时候我们需要写
第二个参数,看下面的代码。
*/
/*
db.workmate.find(
{"skill.skillOne":"HTML+CSS"},
{name:true,"skill.skillOne":true}
)
*/
/*
结果:
{ "_id" : ObjectId("5b8e908d081ab44f912d4485"), "name" : "JSPang", "skill" : { "skillOne" : "HTML+CSS" } }
{ "_id" : ObjectId("5b8e908d081ab44f912d4486"), "name" : "ShengLei", "skill" : { "skillOne" : "HTML+CSS" } }
{ "_id" : ObjectId("5b8e908d081ab44f912d4489"), "name" : "LiangPeng", "skill" : { "skillOne" : "HTML+CSS" } }
{ "_id" : ObjectId("5b8e908d081ab44f912d448a"), "name" : "HouFei", "skill" : { "skillOne" : "HTML+CSS" } }
{ "_id" : ObjectId("5b8e908d081ab44f912d448d"), "name" : "JiaPeng", "skill" : { "skillOne" : "HTML+CSS" } }
{ "_id" : ObjectId("5b8e908d081ab44f912d448e"), "name" : "LiJia", "skill" : { "skillOne" : "HTML+CSS" } }
*/
// 细心的小伙伴会发现还不够完美,多了一个ID字段,这个也不是我们想要的,这时候只要把_id:false就可以了。当然这里的false
// 和true,也可以用0和1表示。
/*
代码:
db.workmate.find(
{'skill.skillOne':'HTML+CSS'},
{
name:true,
'skill.skillOne':true,
'_id':0
}
)
*/
/*
结果:
{ "name" : "JSPang", "skill" : { "skillOne" : "HTML+CSS" } }
{ "name" : "ShengLei", "skill" : { "skillOne" : "HTML+CSS" } }
{ "name" : "LiangPeng", "skill" : { "skillOne" : "HTML+CSS" } }
{ "name" : "HouFei", "skill" : { "skillOne" : "HTML+CSS" } }
{ "name" : "JiaPeng", "skill" : { "skillOne" : "HTML+CSS" } }
{ "name" : "LiJia", "skill" : { "skillOne" : "HTML+CSS" } }
*/
// 其实这些查找操作,都是在作等于的阶段,但是不光只有等于查询,我们需要更多的查询条件。
// 不等修饰符
/*
小于($lt):英文全称less-than
小于等于($lte):英文全称less-than-equal
大于($gt):英文全称greater-than
大于等于($gte):英文全称greater-than-equal
不等于($ne):英文全称not-equal
*/
// 我们现在要查找一下,公司内年龄小于30大于25岁的人员(显示姓名,爱好1,年龄)。看下面的代码。
/*
db.workmate.find(
{
age:{$lt:30,$gt:25}
},
{
name:true,
'skill.skillOne':true,
'_id':false,
'age':true
}
)
*/
/*
结果
{ "name" : "LiangPeng", "age" : 28, "skill" : { "skillOne" : "HTML+CSS" } }
{ "name" : "JiaPeng", "age" : 29, "skill" : { "skillOne" : "HTML+CSS" } }
{ "name" : "LiJia", "age" : 26, "skill" : { "skillOne" : "HTML+CSS" } }
*/
// 日期查找
//MongoDB也提供了方便的日期查找方法,现在我们要查找注册日期大于2018年1月10日的数据,我们可以这样写代码。
/*
代码:
db.workmate.find(
{
regeditTime:{$gt:startDate}
},
{
name:true,
age:true,
'skill,skillOne':true,
'_id':0
}
)
*/
/*
结果: 10个就对了
{ "name" : "JSPang", "age" : 33 }
{ "name" : "ShengLei", "age" : 31 }
{ "name" : "MinJie", "age" : 18 }
{ "name" : "XiaoWang", "age" : 25 }
{ "name" : "LiangPeng", "age" : 28 }
{ "name" : "HouFei", "age" : 25 }
{ "name" : "LiuYan", "age" : 35 }
{ "name" : "DingLu", "age" : 20 }
{ "name" : "JiaPeng", "age" : 29 }
{ "name" : "LiJia", "age" : 26 }
*/
```
## 第11节:查询:find的多条件查询
很多时候我们需要查询的值不只是有一个简单的条件,比如我们现在要查询一下同事中是33岁和25岁的,还比如我们要查询同事中大于30岁并且会PHP技能的。MongoDB在这方面也支持的很好,我们来学习一下。
```javascript
// 第11节:查询:find的多条件查询
/*
很多时候我们需要查询的值不只是有一个简单的条件,比如我们现在要查询一下同事中是33岁和25岁的,还比如我们要查询
同事中大于30岁并且会PHP技能的。MongoDB在这方面也支持的很好,我们来学习一下。
*/
// $in修饰符 (一键多值的查询)
// in修饰符可以轻松解决一键多值的查询情况。
// 就如上面我们讲的例子,现在要查询同事中年龄是25岁和33岁的信息。
/*
代码:
db.workmate.find(
{
age:{$in:[25,33]}
},
{
name:1,
age:1,
'_id':0,
'skill.skillOne':1
}
)
*/
/*
结果:
{ "name" : "JSPang", "age" : 33, "skill" : { "skillOne" : "HTML+CSS" } }
{ "name" : "XiaoWang", "age" : 25, "skill" : { "skillOne" : "PhotoShop" } }
{ "name" : "HouFei", "age" : 25, "skill" : { "skillOne" : "HTML+CSS" } }
*/
// $nin修饰符
// 于$in相对的修饰符是$nin,就是查询除了$in条件以为的指
// 小伙伴们可以自己进行练习一下,这里我就不作过多的演示了。
// $or修饰符 (多个键值的情况)
/*
它用来查询多个键值的情况,就比如查询同事中大于30岁或者会做PHP的信息。
主要区别是两个Key值。$in修饰符是一个Key值,这个需要去比较记忆。
*/
// 就比如查询同事中大于30岁或者会做PHP的信息
/*
代码:
db.workmate.find(
{
$or:[
{age:{$gte:30}},
{'skill.skillThree':'PHP'}
]
},
{
name:true,
age:true,
'skill.skillThree':true,
'_id':false
}
)
*/
/*
结果:
{ "name" : "JSPang", "age" : 33, "skill" : { "skillThree" : "PHP" } }
{ "name" : "ShengLei", "age" : 31, "skill" : { "skillThree" : "PPT" } }
{ "name" : "LiuYan", "age" : 35, "skill" : { } }
{ "name" : "JiaPeng", "age" : 29, "skill" : { "skillThree" : "PHP" } }
{ "name" : "LiJia", "age" : 26, "skill" : { "skillThree" : "PHP" } }
*/
// or很好理解,就是或者的意思,我们查出来的结果也是一样的,查出了年龄大于30岁的,或者会做PHP的信息
// $nor修饰符
// 和$or相反
// $and修饰符 (多个key同时满足)
/*
$and用来查找几个key值都满足的情况,比如要查询同事中大于30岁并且会做PHP的信息,这时需要注意的是这两
项必须全部满足。当然写法还是比较简单的。只要把上面代码中的or换成and就可以了。
*/
// 比如要查询同事中大于30岁并且会做PHP的信息
/*
代码:
db.workmate.find(
{
$and:[{age:{$gt:30}},{'skill.skillThree':'PHP'}]
},
{name:1,age:1,'skill.skillThree':1,'_id':0}
)
*/
/*
结果:
{ "name" : "JSPang", "age" : 33, "skill" : { "skillThree" : "PHP" } }
*/
// $not修饰符
/*
它用来查询除条件之外的值,比如我们现在要查找除年龄大于20岁,小于30岁的人员信息。
需要注意的是$not修饰符不能应用在条件语句中,只能在外边进行查询使用。
*/
// 查找除年龄大于20岁,小于30岁的人员信息
/*
代码:
db.workmate.find({age:{$not:{$lte:30,$gte:20}}},{name:1,age:1,'_id':0})
*/
/*
结果:
{ "name" : "JSPang", "age" : 33 }
{ "name" : "ShengLei", "age" : 31 }
{ "name" : "MinJie", "age" : 18 }
{ "name" : "LiuYan", "age" : 35 }
*/
/*
总结:这节课的知识比较简单,但是要区分记忆,很容易搞混。幸运的是这里已经为你准备好了学习笔记。当你忘记的时候过来看看吧。
*/
/*
个人练习
1. 大于30岁,并且会PHP,列出人名和其他信息
// db.workmate.find({$and:[{age:{$gt:30}},{'skill.skillThree':'PHP'}]},{name:1,age:1,'_id':0,'skill.skillThree':1})
2. 大于20岁的
// db.workmate.find({age:{$gt:20}},{name:1,age:1,'_id':0})
3. 大于20岁,或者会HTML+CSS技术的
*/
```
## 第12节:查询:find的数组查询
```javascript
// 第12节:查询:find的数组查询
/*
这节主要学习数组的查询,在学习update时就花了重墨去讲数组的操作,可见数组的操作在MongoDB中很受重视,因为稍微
大型一点的项目,设计的数据集合都复杂一些,都会涉及数组的操作。
*/
// 完善数据
// 以前的我们的workmate集合对数组涉及还很少,现在在数据中加入了兴趣(interest),并且给每个人加入了一些兴趣,
// 比如有写代码,做饭,看电影…..
/*
当然这些数据你可以自己随意构建,但是如果你不想自己费事费脑,这里也为你准备好了数据,你只要把以前的表删除(drop)
掉,重新载入(load)就可以了。
*/
var workmate1 = {
name: 'JSPang',
age: 33,
sex: 1,
job: '前端',
skill: {
skillOne: 'HTML+CSS',
skillTwo: 'JavaScript',
skillThree: 'PHP'
},
regeditTime: new Date(),
interest: ['看电影', '看书', '吃美食', '钓鱼', '旅游']
}
var workmate2 = {
name: 'ShengLei',
age: 31,
sex: 1,
job: 'JAVA后端',
skill: {
skillOne: 'HTML+CSS',
skillTwo: 'J2EE',
skillThree: 'PPT'
},
regeditTime: new Date(),
interest: ['篮球', '看电影', '做饭']
}
var workmate3 = {
name: 'MinJie',
age: 18,
sex: 0,
job: 'UI',
skill: {
skillOne: 'PhotoShop',
skillTwo: 'UI',
skillThree: 'PPT'
},
regeditTime: new Date(),
interest: ['做饭', '画画', '看电影']
}
var workmate4 = {
name: 'XiaoWang',
age: 25,
sex: 1,
job: 'UI',
skill: {
skillOne: 'PhotoShop',
skillTwo: 'UI',
skillThree: 'PPT'
},
regeditTime: new Date(),
interest: ['写代码', '篮球', '画画']
}
var workmate5 = {
name: 'LiangPeng',
age: 28,
sex: 1,
job: '前端',
skill: {
skillOne: 'HTML+CSS',
skillTwo: 'JavaScript',
},
regeditTime: new Date(),
interest: ['玩游戏', '写代码', '做饭']
}
var workmate6 = {
name: 'HouFei',
age: 25,
sex: 0,
job: '前端',
skill: {
skillOne: 'HTML+CSS',
skillTwo: 'JavaScript',
},
regeditTime: new Date(),
interest: ['化妆', '读书', '做饭']
}
var workmate7 = {
name: 'LiuYan',
age: 35,
sex: 0,
job: '美工',
skill: {
skillOne: 'PhotoShop',
skillTwo: 'CAD',
},
regeditTime: new Date(),
interest: ['画画', '聚会', '看电影']
}
var workmate8 = {
name: 'DingLu',
age: 20,
sex: 0,
job: '美工',
skill: {
skillOne: 'PhotoShop',
skillTwo: 'CAD',
},
regeditTime: new Date(),
interest: ['美食', '看电影', '做饭']
}
var workmate9 = {
name: 'JiaPeng',
age: 29,
sex: 1,
job: '前端',
skill: {
skillOne: 'HTML+CSS',
skillTwo: 'JavaScript',
skillThree: 'PHP'
},
regeditTime: new Date(),
interest: ['写代码', '篮球', '游泳']
}
var workmate10 = {
name: 'LiJia',
age: 26,
sex: 0,
job: '前端',
skill: {
skillOne: 'HTML+CSS',
skillTwo: 'JavaScript',
skillThree: 'PHP'
},
regeditTime: new Date(),
interest: ['玩游戏', '美食', '篮球']
}
var db = connect('demo12');
var workmateArray = [workmate1, workmate2, workmate3, workmate4, workmate5, workmate6, workmate7, workmate8, workmate9, workmate10];
db.workmate.insert(workmateArray);
print('[SUCCESS]:The data was inserted successfully');
// 基本数组查询
/*
比如现在我们知道了一个人的爱好是’画画’,’聚会’,’看电影’,但我们不知道是谁,这时候我们就可以使用最简单的数组查询
(实际工作中,这种情况基本不常用,所以这种查询只作知识点储备就可以了)
*/
// db.workmate.find({interest:['画画','聚会','看电影']},{name:true,_id:0,interest:1,age:1})
/*
结果:
{ "name" : "LiuYan", "age" : 35, "interest" : [ "画画", "聚会", "看电影" ] }
*/
// 在终端中运行后,我们得到了数据。这时候我们说,想查出看兴趣中有看电影的员工信息。按照正常逻辑,应该使用下面的代码。
/*
// 错误做法. 这个是最准确的匹配,如果有多个,则查不到
db.workmate.find({interest:['看电影']},
{name:1,interest:1,age:1,_id:0}
)
*/
/*
运行后,并没有如我们所愿得到相应的人员数据,数据为空。那问题出现在哪里?问题就在于我们写了一个中括号([]),
因为加上中括号就相当于完全匹配了,所以没有得到一条符合查询条件的数据。我们去掉中括号再看看结果。
*/
/*
// 正确做法
db.workmate.find({interest:'看电影'},
{name:1,interest:1,age:1,_id:0}
)
*/
/*
结果:
{ "name" : "JSPang", "age" : 33, "interest" : [ "看电影", "看书", "吃美食", "钓鱼", "旅游" ] }
{ "name" : "ShengLei", "age" : 31, "interest" : [ "篮球", "看电影", "做饭" ] }
{ "name" : "MinJie", "age" : 18, "interest" : [ "做饭", "画画", "看电影" ] }
{ "name" : "LiuYan", "age" : 35, "interest" : [ "画画", "聚会", "看电影" ] }
{ "name" : "DingLu", "age" : 20, "interest" : [ "美食", "看电影", "做饭" ] }
*/
// 这就是我们在数组中查询一项的方法,这也是数组查询的最简单用法。
// $all-数组多项查询 (同时满足)
/*
现在我们的条件升级了,要查询出喜欢看电影和看书的人员信息,也就是对数组中的对象进行查询,这时候要用到一个新的
查询修饰符$all。看下面的例子:
*/
db.workmate.find({interest:{$all:['看电影','看书']}},{name:1,_id:0,interest:1,age:1})
/*
结果:
{ "name" : "JSPang", "age" : 33, "interest" : [ "看电影", "看书", "吃美食", "钓鱼", "旅游" ] }
*/
// $in-数组的或者查询 (满足其中一项即可)
/*
用$all修饰符,是需要满足所有条件的,$in主要满足数组中的一项就可以被查出来(有时候会跟$or弄混)。
比如现在要查询爱好中有看电影的或者看书的员工信息。
*/
db.workmate.find({ interest: { $in: ['看电影', '看书'] } }, { name: 1, age: 1, _id: 0, interest: 1});
/*
结果:
{ "name" : "JSPang", "age" : 33, "interest" : [ "看电影", "看书", "吃美食", "钓鱼", "旅游" ] }
{ "name" : "ShengLei", "age" : 31, "interest" : [ "篮球", "看电影", "做饭" ] }
{ "name" : "MinJie", "age" : 18, "interest" : [ "做饭", "画画", "看电影" ] }
{ "name" : "LiuYan", "age" : 35, "interest" : [ "画画", "聚会", "看电影" ] }
{ "name" : "DingLu", "age" : 20, "interest" : [ "美食", "看电影", "做饭" ] }
*/
// $size-数组个数查询
/*
$size修饰符可以根据数组的数量查询出结果。比如现在我们要查找兴趣的数量是5个人员信息,这时候就可以使用$size。
*/
db.workmate.find({interest:{$size:5}},{name:1,age:1,_id:0,interest:1})
/*
结果:
{ "name" : "JSPang", "age" : 33, "interest" : [ "看电影", "看书", "吃美食", "钓鱼", "旅游" ] }
*/
// 这时候是5项爱好的人员就会显示出来了。
// $slice-显示选项
/*
有时候我并不需要显示出数组中的所有值,而是只显示前两项,比如我们现在想显示每个人兴趣的前两项,而不是把每个
人所有的兴趣都显示出来。
*/
// db.workmate.find({},{interest:{$slice:2},name:1,age:1,_id:0,interest:1}) //错误写法,如果有interest显示选项了,就不需要再为1了,不应该写了
db.workmate.find({}, { interest: { $slice: 2 }, name: 1, age: 1, _id: 0})
/*
结果:
{ "name" : "JSPang", "age" : 33, "interest" : [ "看电影", "看书" ] }
{ "name" : "ShengLei", "age" : 31, "interest" : [ "篮球", "看电影" ] }
{ "name" : "MinJie", "age" : 18, "interest" : [ "做饭", "画画" ] }
{ "name" : "XiaoWang", "age" : 25, "interest" : [ "写代码", "篮球" ] }
{ "name" : "LiangPeng", "age" : 28, "interest" : [ "玩游戏", "写代码" ] }
{ "name" : "HouFei", "age" : 25, "interest" : [ "化妆", "读书" ] }
{ "name" : "LiuYan", "age" : 35, "interest" : [ "画画", "聚会" ] }
{ "name" : "DingLu", "age" : 20, "interest" : [ "美食", "看电影" ] }
{ "name" : "JiaPeng", "age" : 29, "interest" : [ "写代码", "篮球" ] }
{ "name" : "LiJia", "age" : 26, "interest" : [ "玩游戏", "美食" ] }
*/
/*
这时候就显示出了每个人兴趣的前两项,如果我们想显示兴趣的最后一项,可以直接使用slice:-1,来进行查询。
*/
db.workmate.find({},{interest:{$slice:-1},name:1,age:1,_id:0})
/*
结果:
{ "name" : "JSPang", "age" : 33, "interest" : [ "旅游" ] }
{ "name" : "ShengLei", "age" : 31, "interest" : [ "做饭" ] }
{ "name" : "MinJie", "age" : 18, "interest" : [ "看电影" ] }
{ "name" : "XiaoWang", "age" : 25, "interest" : [ "画画" ] }
{ "name" : "LiangPeng", "age" : 28, "interest" : [ "做饭" ] }
{ "name" : "HouFei", "age" : 25, "interest" : [ "做饭" ] }
{ "name" : "LiuYan", "age" : 35, "interest" : [ "看电影" ] }
{ "name" : "DingLu", "age" : 20, "interest" : [ "做饭" ] }
{ "name" : "JiaPeng", "age" : 29, "interest" : [ "游泳" ] }
{ "name" : "LiJia", "age" : 26, "interest" : [ "篮球" ] }
*/
```
## 第13节:查询:find的参数使用方法
```javascript
// 第13节:查询:find的参数使用方法
/*
前边已经讲了3节查询,都是在操作find方法的第一个参数(query)和第二个参数(fields)。
find还有几个常用的参数,这些参数多用在分页和排序上。这节我们就把这些常用的选项说一说,
理解后我们演示一个分页的效果。
*/
// find参数:
// db.集合.find(query,fields).其他参数
/*
1. - query: 这个就是查询条件,MongoDB默认的第一个参数
2. - fields:(返回内容)查询出来后显示的结果样式,可以用true和false控制是否显示。
3. - limit:返回的数量,后边跟数字,控制每次查询返回的结果数量。
4. - skip:跳过多少个显示,和limit结合可以实现分页。
5. - sort:排序方式,从小到大排序使用1,从大到小排序使用-1
*/
// 分页demo
/*
明白了上面这些选项,现在可以作一个最简单的分页,我们把同事集合(collections)进行分页,每页显示两个,
并且按照年龄从小到大的顺序排列。
*/
db.workmate.find({},{name:1,age:1,_id:0,interest:{$slice:1}}).limit(0).skip(2).sort({age:1});
// $where修饰符
/*
它是一个非常强大的修饰符,但强大的背后也意味着有风险存在。它可以让我们在条件里使用javascript的方法来进行
复杂查询。我们先来看一个最简单的例子,现在要查询年龄大于30岁的人员。
*/
db.workmate.find({$where:'this.age>30'},{name:1,age:1,_id:0}).sort({age:1}) //this指向的是workmage(查询集合本身)
/*
结果:
{ "name" : "ShengLei", "age" : 31 }
{ "name" : "JSPang", "age" : 33 }
{ "name" : "LiuYan", "age" : 35 }
*/
/*
这里的this指向的是workmate(查询集合)本身。这样我们就可以在程序中随意调用。虽然强大和灵活,但是这种查询对于数据库的压力
和安全性都会变重,所以在工作中尽量减少$where修饰符的使用。
*/
```
## 第14节:查询:find如何在js文本中使用
```javascript
// 第14节:查询:find如何在js文本中使用
/*
前边使用find都是JS在文本中写完,然后复制到终端中执行,这样非常麻烦。在讲的过程中已经有很多小伙伴在问我如何像写
update语句一样,在文本中直接运行。这节课我们就学习一下如何直接在文本中执行。
*/
// hasNext循环结果
// 想在文本中执行我们的find语句要用到游标和循环的操作,先看一下代码,代码中我已经对每一句进行了注释。
// var db= connect('demo12'); //进行链接对应的集合collections
// var result=db.workmate.find(); //声明变量result, 并把查询结果赋值给result
// while(result.hasNext()){ //利用游标的hanNext()进行循环输出结果
// printjson(result.next()); //用json格式打印结果
// }
// 写完后,现在你只需要在终端中进行load()就可以执行了,再也不用麻烦的复制粘贴了。
// forEach循环
/*
利用hasNext循环结果,需要借助while的帮助,MongoDB也为我们提供了forEach循环,现在修改上边的代码,使用forEach循环来输出结果。
*/
var db=connect('demo12');
var result=db.workmate.find();
result.forEach(function(val){
printjson(val);
})
/*
作为个人觉的forEach循环更为优雅。这两种方法都是非常不错的,凭借自己爱好进行选择吧。
总结:那我们MongoDB的基础部分就全部讲完了,我们学会了它的增、删、改、查,你也可以使用MongoDB进行一些操作了。
需要注意的是,只是这篇文章的完结,下篇文章我们进行讲解MongoDB,开始讲解MongoDB的索引。
*/
// 个人练习
/* 虽然是这样查出来了,但是查出来的是所有,如何按照我之前的条件去查找呢? */
// 1. 查同时爱好里面有看电影和做饭的人,按照年龄从小到大排序,并列出他的爱好出来
var db=connect('demo12');
var result=db.workmate.find({age:{$gt:30}},{name:1,age:1,_id:0}).sort({age:1});
result.forEach(function(val){
printjson(val)
})
```
## 第15节:索引:构造百万级数据
```javascript
// 第15节:索引:构造百万级数据
/*
引的性能提现必须要有大量数据才能看出来,你说你有10条20条数据,这是根本看不出来效果的,
这节课就通过随机数的方法,创造出一个百万级数据的数据库出来。(建议收看视频学习)。
*/
// 制作随机数方法:
/*
我们要想生成一个百万级的数据集合,必须要有随机数的参与,我们需要写一个随机数的方法。下面的代码,创建了一个随机数方法。
//生成随机数
function GetRandomNum(min,max){
let range = max-min; //得到随机数区间
let rand = Math.random(); //得到随机值
return (min + Math.round(rand *range)); //最小值+随机数取整
}
console.log(GetRandomNum(10000,99999));
*/
// 制作随机用户名
/*
有了随机数的方法,我们就可以制作一个随机生成的用户名。目的是存在不同的用户名,方便我们测试查询速度。
//生成随机数
function GetRandomNum(min,max){
let range = max-min; //得到随机数区间
let rand = Math.random(); //得到随机值
return (min + Math.round(rand *range)); //最小值+随机数取整
}
//console.log(GetRandomNum(10000,99999));
//生成随机用户名
function GetRadomUserName(min,max){
let tempStringArray= "123456789qwertyuiopasdfghjklzxcvbnm".split("");//构造生成时的字母库数组
let outPuttext = ""; //最后输出的变量
//进行循环,随机生产用户名的长度,这里需要生成随机数方法的配合
for(let i=1 ;i
*/
// 比如我们现在不小心删除了一个collections的数据,要进行恢复。现在删除randomInfo集合。
// db.randomInfo.drop();
// 使用命令进行恢复
// mongorestore --host 127.0.0.1 --port 27017 D:/databack/
// 总结:
/*
两个命令很简单,甚至你可以写成脚本和定时任务,让他每天自己执行。但是如果你真的使用了MongoDB数据库,
这是一个最基本的操作,还是要会使用的。
*/
```
## 第21节:管理:图形界面管理(完结)
- 使用的是mongodb官方提供的mongodb compass的图形界面