MongoDB初识
1、数据库简介(Database)
数据库是按照数据结构来组织、存储和管理数据的仓库。
我们的程序都是在内存中运行的,一旦程序运行结束或者计算机断电,程序运行中的数据都会丢失。
所以我们就需要将一些程序运行的数据持久化到硬盘之中,以确保数据的安全性。而数据库就是数据持久化的最佳选择。说白了,数据库就是存储数据的仓库。
2、数据库主要分成两种:
(1)关系型数据库
●MySQL、Oracle、 DB2、SQL Server
…
关系数据库中全都是表
例如:
(2)非关系型数据库
●MongoDB、Redis …
●键值对数据库
●文档数据库MongoDB
3、MongoDB简介
MongoDB是为快速开发互联网Web应用而设计的数据库系统。MongoDB的设计目标是极简、灵活、作为Web应用栈的一部分。
MongoDB的数据模型是面向文档的,所谓文档是一种类似于JSON的结构。
下载地址
https://www.mongodb.com/
MongoDB的版本偶数版本为稳定版,奇数版本为开发版。
MongoDB对于32位系统支持不佳,所以3.2版本以后没有再对32位系统的支持。
安装MongoDB后
1、将 C: \Prograr1 Files\MongoDb\Server\3.2\bin 添加至环境变量
2、在c盘根目录创建一个文件夹data
3、在data中创建一个文件夹db,用于存放数据库里的内容
4、打开cmd命令行窗口,输入mongod启动mongodb服务器,并最小化该窗口
注意:
(1)32位系统!!第一次!!启动服务器时需输入
mongod --storageEngine=mmapv1
再次启动直接mongod 即可
(2)mongod --dbpath C: \Users\ai\Desktop\data\db 可指定任意数据库存放内容的路径
mongod --dbpath C: \Users\ai\Desktop\data\db --port 10086 可指定端口号
5、再打开cmd命令行窗口,输入mongo连接服务器
数据库的服务器
服务器用来保存数据
mongod 用来启动服务器
数据库的客户端
客户端用来操作服务器,对数据进行增删改查的操作
mongo 用来启动客户端
将MongoDB设置为系统服务(可选)
可以自动在后台启动,不需要每次都手动启动
1、在c盘根目录创建data,在data下创建db和log文件夹
2、创建配置文件,在目录c:\Program Files\MongoDB\Server\3.2下添加一个配置文件mongod.cfg,写入
systemLog:
destination: file
path: c:\data\log\mongod.log
storage:
dbpath: c:\data\db
3、以管理员的身份打开命令行窗口,执行如下的命令
sc.exe create MongoDB binPath= "\"C:\Program Files\MongoDB\Server\3.2\bin\mongod.exe\" --service --config=\"C: \Progran
Files\MongoDB\Server\3.2\mongod.cfg\"" DisplayName= "MongoDB" start= "auto"
4、任务栏右键任务管理器,点击服务,找到mongodb选择启动该服务
5、如杲启动失败,证明上边的操作有误,在挖制台输入sc delete MongoDB 删除之前配置的服务然后从第一步再来一次
4、MongoDB的图形化界面操作
另一款软件
5、MongoDB的基本操作
三个概念:
一个服务器里可有多个数据库
数据库( database )
一数据库是一个仓库,在仓库中可以存放集合。
集合( collection )
集合类似于数组,在集合中可以存放文档。
文档( document )
文档数据库中的最小单位,我们存储和操作的内容都是文档。
因此操作MongoDB就是操作文档,在MongoDB中,数据库和文档无须手动创建,当我们创建文档时,如果文档所在的集合或数据库不存在会自动创建数据库和集台
基本指令
show data
【show database:显示当前的所有数据库】
【use 数据库名:进入指定的数据库中】
abc数据库不存在,当向abc数据库插入文档时,自动创建该abc数据库
【db:表示当前所处的数据库,在哪个数据库里db就是哪个数据库
】
【show connections :显示数据库中所有的集合】
MongoDB的CRUD增删改查
向数据库中插入文档
【db. collection. insert (doc):向集合名为collection中插入一个文档】
例子:向test数据库中的,stus集合中插入一个新的学生对象
{nane:“孙悟空”, age:18, gender:“男”}
db. stus. insert ( {name: “孙悟空”,age:18,gender:“男”})
插入数据的同时,自动创建了数据库与集合,因此无需手动创建数据库与集合
当我们向集合中插入文档时,如果没有给文档指定_ id属性, 则数据库会自动为文档添加 _id,该属性用来作为文档的唯一标识,_id可以自己指定, 如果我们指定了数据库就不会在添加了,如果自己指定 id 也必须确保它的唯一性
【db. collection. find ():查询当前集合名为collection中的所有的文档,返回一个数组,可通过索引查找】
find()可接受一个对象作为条件参数
【db. collection. findOne () :用来查询集合中符合条件的第一个文档,返回一个文档对象】
【db.collection. find({ }) . count ():查询所有结果的数量】
【db. collection. update (查询条件,新对象),update ()默认情况下会使用新对象来替换旧的对象】
如果需要修改指定的属性,而不是替换,需要使用“修改操作符”来完成修改,$ set 可用来修改文档中的指定属性,$ unset 可用来删除文档的指定属性,update 默认只更改第一个符合查询条件的对象,若想修改多个,可设定multi参数
例如给沙和尚的增加一些属性
例如删除沙和尚的address
【db.collection.updateMany ():同时修改多个符合条件的文档】
【db.collection.updateOne ():修改一个符合条件的文档】
【db.collection.replaceOne ():替换一个文档】
【db.collection.remove ():删除符合条件的所有文档,必须传递参数】默认情况删除多个符合条件的,可根据条件删除文档,传递条件的方式与find()一样若想删除一个,则将第二个参数设置为true
如果只传递一个空对象作为参数,则会一个一个的删除集合中的所有文档,db.stus.remove () 错误,应该为db.stus.remove ({}) ,必须传递参数!
【db.stus.drop() :直接删除集合】
【db.dropDatabase () :删除数据库】
执行db.stus.remove ( {age:28} ,true) 只删除一个,使用db.stus. find({}) 查询一下,只剩一个
【db.collection.deleteOne ()】
【db.collection.deleteMany ()】
一般数据库中的数据都不会制除,所以删除的方法很少调用,一般会在数据中添加一个字段,来表示数据是否被删除
只查询未删除
6、文档之间的关系
一对一
在MongoDB中,可以通过内嵌文档的形式来体现出一对一的关系
db.WifeAndHusband.insert([
{
name:"黄蓉"
husband:{
name:"郭靖"
}
},{
name:"潘金莲"
husband:{
name:"武大郎"
}
}
])
db.WifeAndHusband.find()
一对多/多对一
也可以通过内嵌文档的形式来体现出一对多的关系
类似一对一,只是把属性变成数组
db.users.insert([{
username:"swk"
},{
username:"zbj"
}
])
db.users.find()
db.order.insert({
list:["苹果","香蕉","大鸭梨"]
user_id:ObiectId ("59c47e35241d8d36a1d50ddf")
})
db.order.find()
如此插入多条
查找用户swk的订单
var user_id = db.users.findOne({username:"swk"})._id
user_id
db.order.find({user_id:user_id}) #查询swk的订单
查询得到的swk的订单如下:
多对多
db.teachers.insert([
{name:"洪七公"},
{name:"黄药师"},
{name:"龟仙人"}
])
db.teachers.find()
db.stus.insert([
{
name:"郭靖",
tech_id:[
ObjectId ("59c4806d241d8d36a1d50de4"),
ObiectId ("59c4806d241d8d36a1d50de5")
]
},
{
name:"孙悟空",
tech_id:[
ObjectId("59c4806d241d8d36a1d50de4"),
ObjectId("59c4806d241d8d36a1d50de5"),
ObjectId("59c4806d241d8d36a1d50de6")
]
}
])
db.stus.find()
7、操作练习
1.进入my test数据库
use my_test
2.向数据库的user集合中插入一个文档
db.users.insert({
username:"sunwukong"
})
3.查询user集合中的文档
db.users.find()
4.统计数据库user集合中文档的数量
db.users.find().count()
5.查询数据库user集合中username为sunwukong的文档
db.users.find({username:"sunwukong"});
6.向数据库user集合中的username为sunwukong的文档,添加一个address属性,属性值为huaguoshan
db.users.update ({ username:"sunwukong"}, {$set: {address: "huagupshan"}})
7.使用{username :“tangseng”}替换username为zhubajie的文档
db.users.replaceOne({username:"zhubajie"},{username:"tangseng"})
8.删除username为sunwukong的文档的address属性
db.users.udpate({username:"sunwukong"},{$unset:{address:1}})
9.向username为sunwukong的文档中,添加一个
hobby:{cities:
[’'beijing",“shanghai”," shenzhen"] , movies: [“sanguo”,“hero”]
}
mongoDB的文档的属性值也可以是一个文档,当一个文档的属性值是文档时,我们称该文档为内嵌文档
db.users.udpate({username:"sunwukong"},{$set: {hobby:{cities:
["beijing","shanghai"," shenzhen"] , movies: ["sanguo","hero"]
}
}})
10.查询喜欢电影hero的文档
db.users.find({"hobby.movies":"hero"})
MongoDB支持直接通过内嵌文档的属性进行查询,如果要查询内嵌文档则可以通过 . 的形式来匹配。如果要通过内嵌文档来对文档进行查询,此时属性必须使用引号
11.向tangseng添加一个新的电影Interstellar
db.user.update({username:"tangseng"},
{$push:{"hobby.movirs:"Interstellar"}
})
$push用于向数组中添加一个新的元素
$addToSet用于向数组中添加一个不重复的新元素,如果数组中已存在了该元素,则不会添加
12.删除喜欢beijing的用户
db.users.remove({"hobby.cities":"beijing"})
13.删除user集合
db.users.remove({})
db.users.drop()
14.向numbers中插入20000条数据
for (var i=1;i<=2000;i++){
db.numbers.insert({num:i});
}
db.numbers.find()
// 或者
var arr=[]
for (var i=1;i<=2000;i++){
arr.push({num:i});
}
db.numbers.insert(arr)
15.查询numbers中num为500的文档
db.numbers.find({num:500})
16.查询numbers中num大于500的文档
db.numbers.find({num:{$gt:500}})
17.查询numbers中num等于500的文档
db.numbers.find({num:{$gte:500}})
18.查询numbers中num小于30的文档
db.numbers.find({num:{$lt:30}})
19.查询numbers中num大于50小于40的文档
db.numbers.find({num:{$gt:40,$lt:50}})
20.查询numbers中num大于19996的文档
db.numbers.find({num:{$gt:19996}})
21.查询numbers中的前10条数据
db.numbers.find().limit(10)
//limit()设置显示数据的上限
21.查询numbers中的11条至20条数据
分页 每页显示10条
1-10
11-20
31-30
…
skip( (页码-1) * 每页显示的条数).limit(每页显示的条数)
db.numbers.find().skip(10).limit(10)
// skip()用于跳过指定数量的数据
22.查询numbers中的21条至30条数据
db.numbers.find().skip(20).limit(10)
//或者
db.numbers.find().limit(10).skip(20)
//效果相同,mongoDB会自动调整limit与skip的位置
23.将部门dept.json和员工emp.json集合导入到数据库中
db.dept.find()
db.emp.find()
24.查询工资小于2000的员工
db.emp.find({sal:{$lt:2000}})
25.查询工资在1000-2000的员工
db.emp.find({sal:{$lt:2000,$gt:1000}})
26.查询工资小于1000或者大于2500的员工
db.emp.find({$or:[{sal:{$lt:1000}},{sal:{$gt:2500}}]})
// $or跟着一个数组,数组里是条件,满足其中一个即可
27.查询财务部的所有员工
var depno = db.dept.findOne({dname:"财务部"}).deptno # 获得财务部的编号10
db.emp.find({depno:depno})
28.查询销售部的所有员工
var depno = db.dept.findOne({dname:"销售部"}).deptno # 获得销售部的编号30
db.emp.find({depno:depno})
29.查询经理编号mgr为7698的所有员工
db.emp.find({mgr:7698})
30.为所有薪资小于或等于1000的员工增加工资400元
db.emp.updateMany({sal:{$lte:1000}},{$inc:{sal:400}})
// $inc在原来值上进行增加
db.emp.find()
// 查询文档时,默认按照_id的值进行排列,值小的在上,值大的在下(升序)
31.按照工资排序
db.emp.find().sort({sal:1})
// sort ()可以用来指定文档的排序的规则,sort ()需要传递一个对象来指定排序规则,sal:1升序,sal:-1降序
32.先按照工资升序,若两个人工资一样,再按照员工编号降序
db.emp.find().sort({sal:1,empno:-1})
// limit skip sort 可以以任意顺序进行调用
33.在查询时,可以在第二个参数的位置来设置查询结果的投影
db.emp.find({},{ename:1})
// ename:1 仅显示员工的姓名,id默认显示
db.emp.find({},{ename:1,_id:0,sal:1})
// _id:0不显示id
8、Mongoose
之前我们都是通过shell来完成对数据库的各种操作的,在开发中大部分时候我们都需要通过程序来完成对数据库的操作。而Mongoose就是一个让我们可以通过Node来操作MongoDB的模块。
Mongoose是一个对象文档模型 ( ODM )库,它对Node原生的MongoDB模块进行了进一步的优化封装,并提供了更多的功能。
在大多数情况下,它被用来把结构化的模式应用到一个MongoDB集合,并提供了验证和类型转换等好处
Mongoose的好处:
●可以为文档创建一个模式结构 ( Schema )
●可以对模型中的对象/文档进行验证
●数据可以通过类型转换转换为对象模型
●可以使用中间件来应用业务逻辑挂钩
●比Node原生的MongoDB驱动更容易
新的对象
●mongoose中为我们提供了几个新的对象
- Schema(模式对象)
●Schema对象定义约束了数据库中的文档结构 - Model
●Model对象作为集合中的所有文档的表示,相当于
MongoDB数据库中的集合collection - Document
●Document表示集合中的具体文档,相当于集合中
的一个具体的文档
打开WebStorm,创建一个mongoose文件夹,在其中新建一个package.json文件,再新建一个helloMongoose.js文件。
1.下载Mongoose
npm i mongoose -- save
2.在项目中引入Mongoose
var mongoose = require("mongoose")
3.连接mongoDB数据库
mongoose.connect ('mongodb://数据库的ip地址:端口号/数据库名', { useMongoClient: true});
如果端口号为默认端口号27017,则可以省略不写
4.断开数据库连接(一般无需)
MongoDB数据库,一般情况下,只需要连接一次,连接一次以后,除非项目停止服务器关闭,否则连接一般不会断开
mongoose.disconnect()
-监听MongoDB数据库的连接状态
在mongoose对象中,有一个屬性叫做connection, 该对象表示的就是数据库连接,通过监视该对象的状态,可以来监听数据库的连接与断开
数据库连接成功的事件
mongoose.connction.once("open",function(){});
数据库断开的事件
mongoose.connction.once("close",function(){});
在helloMongoose.js文件中写入
var mongoose = require("mongoose");
//连接数据库
mongoose.connect("mongodb://127.0.0.1/mongoose_test",{useMongoClient:true});
mongoose.connection.once("open",function() {
console.log("数据库连接成功~~~");
});
mongoose.connection.once("close",function() {
console.log("数据库连接已经断开~~~") ;
});
//断开数据库
mongoose.disconnect()