下载mongo
配置mongo
容器命名
打开mongo映像,容器名称推荐mongo-端口名称
创建目录
在 File Station 新建文件夹,并在configdb内放入一个 configdb.conf 的空文档
高级设置
创建mongodb容器 配置存储空间路径
本地端口绑定为容器端口
下方输入命令
mongod --config /data/configdb/mongod.conf
应用并运行
创建超级用户
打开容器,终端机 → 新增 → bash:
ll // 查看数据库目录
mongo // 进入mongo数据库
use admin
db.createUser({user: "test1", pwd: "test1", roles: [{role: "root", db: "admin"}]})
exit // 退出
普通用户:
use test2db
db.createUser({user: "test2", pwd: "test2", roles: [{role: "readWrite", db: "test2db" }]})
创建完超级用户,需要把数据库的安全保障打开,数据库的安全配置,用户权限配置策略,之后找教程了解
更改配置文件
打开mongod.conf
security:
authorization: enabled
注意层级换行用四个空格,不要用tab,key: value 中间也要有一个空格,不然会报错
mongodb+srv://maxuan:601109@192.168.31.107:27017/admin
安装robot 3t
下载
Robo 3T | Free, open-source MongoDB GUI
连接
安装完成后,点击左上角 Create → 修改Name 和 Address ,第二个选项卡 Authentication
勾选上下两个checkbox,填写用户名 密码,点击左下方 Test,链接成功 Save
新建数据库
连接名右键 → Creat Database → 输入数据库名 → 确定
右键Collections → Create Collection 来创建集合
grade右键 Insert Document 在文档内插入数据
点击save保存,grade内就被插入了一条数据
Node.js连接mongodb
npm init -y
npm i mongodb -s
server.js
// 获取实例
const MongoClient = require('mongodb').MongoClient;
// 异步变同步自执行函数包裹
(async function() {
// 设置服务端信息
const client = new MongoClient('mongodb://maxuan:601109@192.168.31.107:27017',{useNewUrlParser:true})
// 连接服务端
await client.connect()
console.log('数据库连接成功');
// 获取数据库
const db = client.db('test')
// 获取集合
const grade = db.collection('grade')
console.log(grade);
// 下方执行操作--------------------------------------------------
// 先删除所有数据
grade.deleteMany()
// 关闭连接
client.close()
})()
nodemon server.js
数据库连接成功
Collection {
s: {
db: Db { s: [Object] },
options: {
raw: false,
promoteLongs: true,
promoteValues: true,
promoteBuffers: false,
ignoreUndefined: false,
ignoreUndefined: false,
bsonRegExp: false,
serializeFunctions: false,
fieldsAsRaw: {}
},
readConcern: undefined,
writeConcern: undefined,
slaveOk: false
}
}
增加
插入一条数据
server.js
const res = await grade.insertOne({
name: 'Max',
age: 23,
hobby:['学习','学习','还是学习'],
score: 60
})
console.log(res)
/* 注意大版本不同返回值也不一样
{
acknowledged: true,
insertedId: new ObjectId("61670a154a298b9852c871ba")
}
*/
数据插入完成后 返回 true 和 新对象的id
插入多条数据
const res = await grade.insertMany([
{name: 'Max',age: 23,hobby:['学习','学习','还是学习'],score: 60},
{name: '李四',age: 40,hobby:['吃饭','睡觉'],score: 60},
{name: '王五',age: 20,hobby:['吃饭','篮球'],score: 60},
{name: '赵六',age: 16,hobby:['学习'],score: 60},
{name: '小丽',age: 38,hobby:['学习'],score: 60},
{name: '小红',age: 40,hobby:['学习'],score: 60},
{name: '小马',age: 27,hobby:['学习'],score: 60},
{name: '小王',age: 59,hobby:['学习'],score: 60},
{name: '小黑',age: 16,hobby:['学习'],score: 60},
{name: '小二',age: 18,hobby:['学习'],score: 60},
])
console.log(res);
/*
{
acknowledged: true,
insertedCount: 10,
insertedIds: {
'0': new ObjectId("61670c4e1363298553df7fd2"),
'1': new ObjectId("61670c4e1363298553df7fd3"),
'2': new ObjectId("61670c4e1363298553df7fd4"),
'3': new ObjectId("61670c4e1363298553df7fd5"),
'4': new ObjectId("61670c4e1363298553df7fd6"),
'5': new ObjectId("61670c4e1363298553df7fd7"),
'6': new ObjectId("61670c4e1363298553df7fd8"),
'7': new ObjectId("61670c4e1363298553df7fd9"),
'8': new ObjectId("61670c4e1363298553df7fda"),
'9': new ObjectId("61670c4e1363298553df7fdb")
}
}
*/
查询
查找一条数据
const res = await grade.findOne({
name: 'Max'
})
console.log(res);
返回结果
{
_id: new ObjectId("61670c4e1363298553df7fd2"),
name: 'Max',
age: 23,
hobby: [ '学习', '学习', '还是学习' ],
score: 60
}
查找聚合全部数据
因为返回的是一个原型对象,需要用toArray() 处理一下
const res = await grade.find().toArray()
console.log(res);
因为返回结果就是所有数据,log不贴了
查找全部数据 附加条件
const res = await grade.find({
name: '李四'
}).toArray()
console.log(res);
/*
[
{
_id: new ObjectId("61670c4e1363298553df7fd3"),
name: '李四',
age: 40,
hobby: [ '吃饭', '睡觉' ],
score: 60
}
]
*/
这里打印结果变成了数组,如果条件共有,则会返回多个
查找范围
比较运算符
- $gt — 大于
- $lt — 小于
- $gte — 大于等于
- $lte — 小于等于
比较运算符
const res = await grade.find({
age: {
$gt: 20 // 大于20岁
}
}).toArray()
逻辑运算符
- $and — 并且
- $or — 或者
- $all — 指定字段中的所有
- $in — 指定字段中的或者
- $size — 指定字段的数据的数量
- $not — 不包含
- $nor — 或者不
$and 并且
and使用短路求值,如果第一个表达式的结果是false,MongoDB将不会执行剩余的表达式;
const res = await grade.find({
$and: [
{name: '王五'},
{age: 20}
]
}).toArray()
/*
[
{
_id: new ObjectId("61670c4e1363298553df7fd4"),
name: '王五',
age: 20,
hobby: [ '吃饭', '篮球' ],
score: 60
}
]
*/
简单的and查询可以隐式省略
const res = await grade.find({
name: '王五',
age: 20
]
}).toArray()
AND查询使用多个表达式指定相同的操作:
db.inventory.find( {
$and : [
{ $or : [ { price : 0.99 }, { price : 1.99 } ] },
{ $or : [ { sale : true }, { qty : { $lt : 20 } } ] }
]
} )
以上字段将会查询price字段值等于0.99或1.99并且sale字段值为true或者qty小于20的所有文档
使用隐式AND操作无法构建此查询,因为它不止一次使用$or操作
$or 或者
const res = await grade.find({
$or:[
{name:'李四'},
{age: 40}
]
}).toArray()
console.log(res);
/*
[
{
_id: new ObjectId("61670c4e1363298553df7fd3"),
name: '李四',
age: 40,
hobby: [ '吃饭', '睡觉' ],
score: 60
},
{
_id: new ObjectId("61670c4e1363298553df7fd7"),
name: '小红',
age: 40,
hobby: [ '学习' ],
score: 60
}
]
*/
$all 指定字段的所有
返回爱好字段的数组内所有包含 ‘ 学习 ’ 的人的数据
const res = await grade.find({
hobby:[
$all: ['学习'],
]
}).toArray()
console.log(res);
$in 指定字段的或者
使用in替换$or操作;
返回爱好字段的数组内所有包含 ‘ 学习 ’ 或 ‘ 睡觉 ’ 的人的数据
const res = await grade.find({
hobby:[
$in: ['学习', '睡觉'],
]
}).toArray()
console.log(res);
$size 指定字段的数据的数量
返回hobby字段数组内,成员有3个的数据
const res = await grade.find({
hobby:[
$size: 3
]
}).toArray()
console.log(res);
$not 不包含
$not执行一个逻辑not操作在指定的表达式并查询到不匹配表达式的文档,这包含不包括字段的文档
db.inventory.find( { price: { $not: { $gt: 1.99 } } } )
此查询将会查询inventory集合中的文档,条件如下: price字段小于等于1.99或者price不存在
{ not: { gt: 1.99 } } 不同于lte操作,{ lte: 1.99 }操作只会返回price字段存在并且小于等于1.99的字段。
记住not做逻辑析取和$ne操作测试字段内容;
使用$not操作时考虑如下操作:
操作$not操作符和其它操作符一致但是会产生一些意想不到的结果,比如数组之类的数据类型;
regex正则表达式操作,使用//或者你的驱动接口代替,使用语言的正则表达式功能创建正则表达式对象;
考虑下面的例子使用模式匹配//:
db.inventory.find( { item: { $not: /^p.*/ } } )
此查询将会查询inventory集合中item字段不是以p开头的所有文档
$nor 或者不
这样返回的结果就不包含name为Max和age为40的人了
const res = await grade.find({
$nor:[
{name:'Max'},
{age: 40}
]
}).toArray()
下面的例子结合比较运算符
// 查询年龄不大于20或者不小于16的人
const res = await grade.find({
$nor:[
{
age: {
$gt: 20
}
},
{
age:{
$lt: 16
}
}
]
}).toArray()
console.log(res);
/*
[
{
_id: new ObjectId("61670c4e1363298553df7fd4"),
name: '王五',
age: 20,
hobby: [ '吃饭', '篮球' ],
score: 60
},
{
_id: new ObjectId("61670c4e1363298553df7fd5"),
name: '赵六',
age: 16,
hobby: [ '学习' ],
score: 60
},
{
_id: new ObjectId("61670c4e1363298553df7fda"),
_id: new ObjectId("61670c4e1363298553df7fdb"),
name: '小二',
age: 18,
hobby: [ '学习' ],
score: 60
}
]
*/
$regex 正则表达式
const res = await grade.find({
name: {
$regex: /^李/
}
}).toArray()
console.log(res);
/*
[
{
_id: new ObjectId("61670c4e1363298553df7fd3"),
name: '李四',
age: 40,
hobby: [ '吃饭', '睡觉' ],
score: 60
},
{
_id: new ObjectId("61670c4e1363298553df7fd7"),
name: '李红',
age: 40,
hobby: [ '学习' ],
score: 60
}
]
*/
分页查询
limit() 查询数量
查询当前聚合的前两条数据
const res = await grade.find().limit(2).toArray()
console.log(res);
skip() 查询跳过
跳过前两条数据,获取后2条数据
const res = await grade.find().skip(2).limit(2).toArray()
sort() 查询排序
返回所有数据,按照年龄正序递增,如果参数为 -1,则是倒序递减
const res = await grade.find().sort({
age: 1
}).toArray()
分页查询示例
索引 - 1 后 × size 获得跳过的数量,第一页为 0,最后一页需要再做处理
const pageIndex = 2 // 当前页面索引
const pageSize = 3 // 一页显示的数据
const res = await grade.find().skip((pageIndex -1)* pageSize).limit(pageSize).toArray()
数据的遍历处理
forEach()
对所有的数据单独处理
res.forEach(ele => {
console.log(ele)
})
map()
所有名字打包为一个数组返回给前端
let names = res.map(ele => ele.name)
console.log(names)
// ['张三', '李四', '王五']
聚合函数
- $sum — 当前组求和
- $avg — 当前组平均值
- $min — 当前组最小值
- $max — 当前组最大值
- $first — 当前组第一条
数组内包裹对象, 聚合结果count对象内 $sum 值为1,表示true,进行求和
$sum 求和
const res = await grade.aggregate([
{
$group: {
_id: '$age',
count: {
$sum: 1
}
}
}
]).toArray()
console.log(res);
/*
[
{ _id: 40, count: 2 },
{ _id: 59, count: 1 },
{ _id: 20, count: 1 },
{ _id: 27, count: 1 },
{ _id: 18, count: 1 },
{ _id: 38, count: 1 },
{ _id: 23, count: 1 },
{ _id: 16, count: 2 }
]
*/
$avg 求平均值
以age分组,$avg平均值函数,指定为score,返回以年龄分组的分数平均数
const res = await grade.aggregate([
{
$group: {
_id: '$age',
avgScore: {
$avg: '$score'
}
}
}
]).toArray()
console.log(res);
/*
[
{ _id: 16, avgScore: 64.66666666666667 },
{ _id: 40, avgScore: 60 },
{ _id: 20, avgScore: 81 },
{ _id: 27, avgScore: 86 },
{ _id: 18, avgScore: 52 },
{ _id: 23, avgScore: 76 }
]
*/
$min 最小值
返回以年龄分组的每组最小分数
const res = await grade.aggregate([
{
$group: {
_id: '$age',
avgScore: {
$min: '$score'
}
}
}
]).toArray()
console.log(res);
$max 最大值
形式同 $min,省略
$first 第一条
返回当前年龄分组的,第一个名字
const res = await grade.aggregate([
{
$group: {
_id: '$age',
avgScore: {
$first: '$name'
}
}
}
]).toArray()
/*
[
{ _id: 16, avgScore: '赵六' },
{ _id: 40, avgScore: '李四' },
{ _id: 20, avgScore: '王五' },
{ _id: 27, avgScore: '小马' },
{ _id: 18, avgScore: '小二' },
{ _id: 23, avgScore: 'Max' }
]
*/
更改
更新一条name为Max的数据,score 为 80
const res = await grade.updateOne(
{
name: "Max"
},
{
$set:{
score: 80
}
}
)
console.log(res);
/*
{
acknowledged: true, // 承认
modifiedCount: 1, // 修改次数
upsertedId: null, // 更新id
upsertedCount: 0, // 插入计数
matchedCount: 1 // 匹配数
}
*/
删除
删除一条name为李四的数据
const res = await grade.deleteOne(
{
name: "李四"
}
)
console.log(res);
/*
{
acknowledged: true,
deletedCount: 1
}
*/