node简介
“Node.js是一个Javascript运行环境(runtime) ,发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装。
客户端和服务端
服务端渲染:可以被爬虫,客户端异步渲染很难被爬虫
客户端渲染:不利于SEO搜索引擎优化
模块
有三种:
1、具名的核心模块
2、用户自己编写的文件模块,相对路径必须加./,可以省略后缀名
没 有全局作用域,只有模块作用域
外部访问不到内部,内部访问不到外部,
要使用模块中的数据,要在模块中导出
3、第三方模块
第三方模块都必须通过npm来下载
使用的时候就可以require的方式进行加载
不能使任何一个第三方包和核心模块的名字一样
require的作用
1、加载文件模块并执行内部方法,
2、拿到被加载的文件模块的导出接口对象
request请求(node 中的请求)
const request=require("request")
核心模块
文件操作:fs
服务器请求:http
路径操作:path
操作系统:os
读取文件
必须引入 fs 核心模块
异步操作
var fs = require("fs")
// 读文件
// 参1:要读取的文件路径
// 参2:回调函数
// error
// 失败,返回错误对象
// 成功,返回null
// data
// 失败,返回错误对象
// 成功,返回读取到的数据
//路径是相对与主目录的,可以省略./
//第二个参数用来转化,可是是我们识别。读出的数据是字符串,可以用JSON
fs.readFile("./nodeStud.md","utf8", (err, data) => {
if (err) {
console.log(err);
console.log("读取文件失败");
return
}
// 浏览器返回16进制数据,toString()进行转化
console.log(data.toString());
})
// 写文件
// 参1:文件路径
// 参2:文件内容
// 参3:回调函数
// 成功:返回null
// 失败:返回错误对象
fs.writeFile("./testFile.md", "5555", (err) => {
if (err) {
console.log(err);
console.log("写入文件失败");
}
})
路径操作url模块
必须引入url核心模块
获取路径中的地址和参数
const url=require("url")
const path=url.parse(req.url, true) //返回一个对象,第一个是路径,第二个参数最好是true,
// path.name 不含参数的路径
// path.query 参数, 第二个参数为true,为对象,反之为字符串
url.resolve(参1,参2) /参1 ,基础url ,参2 ,目标url
路径处理Path模块
必须引入path核心模块
path.extname(路径) //路径信息扩展名
path.join("",...)//可以多个路径拼接在一起,生成规范的路径
path.resolve("",...)//会自动拼接系统地址,多个路径拼接在一起,生成规范的路径
__dirname //获取当前执行的目录
__filename //获取当前的文件
path.parse() //解析路径 根路径 ,目录 文件名 ,文件类型
os操作系统信息
必须引入os核心模块
os.cpus() //操作系统信息
os.totalmem()//内存信息
os.arch() //内存架构 ,x64
创建服务器
必须引入http核心模块
const http = require("http")
const fs = require("fs")
// 创建一个服务器,可以开多个服务器,但是端口号不能一样
const server = http.createServer()
/*
服务器响应
request请求事件的回调,有两个参数
Request 请求对象
用来回去用户的一些请求信息,例如请求路径
Response 响应对象
给客户端发送响应信息
有一个write()用来给客户发消息,但是必须要有一个end()
一般用end结束响应,并发送数据
*/
server.on("request", (req, res) => {
/*
req.url 请求路径,以/开头 , 通过不同的路径,响应不同的数据
一般req.url=="/" ,请求的首页
响应数据只能是字符串,二进制
res.setHeader("Content-Type", "text/plain;charset=utf-8")
服务器默认编码uft-8,
text/plain;charset=utf-8 普通文本
text/html;charset=utf-8 html 格式的字符串
访问图片,不需要编码
image/png, image/jpeg
*/
fs.readFile("./resourse/xx1.png", (err, data) => {
if (!err) {
res.setHeader("Content-Type", "image/png")
res.end(data)
} else {
res.end("错误")
}
})
})
// 绑定监听端口
server.listen(3000, () => {
console.log("服务器启动成功,通过ip:端口号,可以访问");
})
模板引擎
art-template
不关心内容,之关系语法
在web中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
xixi
</div>
</body>
<script src="../node_modules/art-template/lib/template-web.js"></script>
<script type="text/template" id="tmep">
<p>{{name}}</p>
<p>{{each hoby}} {{$value}}{{/each}}</p>
</script>
<script>
var rer = template('tmep', {
name: "afdfa",
hoby: [
"daf", "adfa"
]
})
console.log(rer);
</script>
</html>
在node中
.js
const template=require("art-template")
const http = require('http')
const server = http.createServer()
const fs = require('fs')
const baseUrl = "./resourse"
server.on("request", (req, res) => {
var url = "/hello.html"
if (req.url != '/') {
url = req.url
}
fs.readFile(baseUrl + url, (err, data) => {
if (!err) {
// render接受字符串
var temp=template.render(data.toString(),{
name: "afdfa",
hoby: [
"daf", "adfa"
]
})
// res.setHeader("Content-Type", " text/html;charset=utf-8")
res.end(temp)
}
})
})
server.listen(3001, (err) => {
console.log('服务器启动');
})
.hello.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<p>gafga</p>
<p>{{name}}</p>
<p>{{each hoby}} {{$value}}{{/each}}</p>
</div>
</body>
</html>
退出
process.exit(1)
数字1,为退出码,也可以是其他的
在控制台,也可以使用ctrl+c
process.exitCode=1
导入导出
require和module.exports(export)
module.exports:公开了指向的对象
**exports:**公开指向的对象的属性,是module.exports的引用
如果一个模块需要导出某一个成员,而非挂载用,module.exports
module.exports进行多个导出时会覆盖
exports.a={}
exports.b=""
module.exports=fun (){}
module.exports=""
//会覆盖
导出多个
module.exports={
}
process
不需要require,自动可以获取
process.env.NODE_ENV //"development"、"production"
输出到命令行
console.log()//打印到命令行console.clear()//清空控制台console.count()//元素计数,会对打印的字符串进行计数console.trace()//打印调用的堆栈踪迹console.time("fun()")//计算函数运行的耗时console.timeEnd("fun()")//计算函数运行的耗时
重定向
通过服务器让客户端重定向
1、状态码设置为
302,临时重定向 ,
301 永久重定向,浏览器会记忆
状态码 res.statusCode=302
2、在响应头通过location告诉客户端往哪里重定向
res. setHeader("Location","/")
优先从缓存中加载
若一个模块已经被重新加载过,当遇到在加载时,不会重新加载,而是重缓存中加载
Apache
const http = require('http')
const server = http.createServer()
const fs = require('fs')
// Apache服务器软件,有一个www默认目录
const baseUrl = "./resourse"
/*
* 1、得到目录列表中的文件名和目录名
* fs.readdir()
* 2、如何将得到的文件名和目录名替换到html中
* 模板引擎
* */
server.on("request", (req, res) => {
var url = "/hello.html"
if (req.url != '/') {
url = req.url
}
fs.readFile(baseUrl + url, (err, data) => {
if (!err) {
fs.readdir("./resourse", (err1, file) => {
var cotent = ''
file.forEach(item => {
cotent += `<h1>${item}</h1>`
})
data = data.toString()
data = data.replace('xixi', cotent)
res.end(data)
})
}
})
})
server.listen(3001, (err) => {
console.log('服务器启动');
})
日志打印
const logger = require("morgan") // 日志
// npm i morgan -s
app.use(logger("dev"))
Express
node中的web框架
模板引擎
art-template
npm install --save art-template
npm install --save express-art-template
/*
*
* express为req相应的对象提供了一个方法:render。
* 但是默认不能使用,需要配置模板引擎,
* res.render('html模板名',{模板数据}),第一参不能写路径,默认去views录查找,
* 修改默认路径,app.set("view",要修改的render函数的默认路径)
*
* */
//个参数配置的文件后缀名,在view中模板文件必须已.html结尾
app.engine('html', require('express-art-template'));
// 2. 设置项目中默认的模板引擎
app.set('view engine', 'html')
// 3.设置默认模板引擎的存放路径
res.render("index.html")
ejs
默认后缀名 index.ejs (在views文件夹下建立index.ejs ,和index.html结构相似)
app.set("views",__dirname+"/views1") /修改保存路径
修改模板引擎的后缀 ejs ->html
app.js
var ejs=require('ejs')
app.engine("html",ejs,__express)
app.set("view engin","html")
npm i ejs --save
app.set("view engine" ,"ejs")
//默认加载模板引擎的文件夹views
//输出对象
res.render("index",{})
//输出html
index.ejs
//数据渲染
<div><%=title%></div>
//html
<div><%-title%></div>
//条件判断
<%if(){%> <span></span> <%}%>
<%if(){%>
<span></span>
<%}else{%>
<span></span>
<%}%>
//for循环
<%for(){%>
<span></span>
<%}%>
//引入公共ejs
<%- include("footer.ejs") %>
get请求
const express=require('express')
// 创建服务器 类似http.createServer()
const app=express()
const fs=require('fs')
// 公开指定目录,可以通过/pub /xxx访问pub下的资源
app.use('/pub/',express.static("./pub/"))
//配置静态目录,使外部可以访问static文件夹下 (同上)
app.use(express.static("static"))
// 当服务器收到get请求时,执行的回调,可以使用req.query来获取查询字符串
app.get("/",(req,res)=>{
// 重定向
res.redirect("/")
res.send("hello 、。")
})
app.get("/具体路径",(req,res)=>{
res.send("hello")
})
// 监听事件
app.listen(3000,()=>{
console.log("服务器启动");
})
post请求
const express=require('express')
// 创建服务器 类似http.createServer()
const app=express()
// post请求解析的中间件
const bodyParse=require('body-parser')
const fs=require('fs')
// 公开指定目录,可以通过/pub /xxx访问pub下的资源
app.use('/pub/',express.static("./pub/"))
/*
* 当服务器收到post请求时,执行的回调,可以用中间件
* npm i body-parser --save
一定要在路由之后
*
* */
// 配置中间件
// parse application/x-www-form-urlencoded
//true 或者false 将会影响post请求的body 数据格式
app.use(bodyParse.urlencoded({extended:false}))
// parse application/json
app.use(bodyParse.json())
app.post("",()=>{
// req.body获取post请求数据
})
// 监听事件
app.listen(3000,()=>{
console.log("服务器启动");
})
路由
app.js
const route=require("./router/routerExpress")
app.use(route)
router.js
// express提供的路由
const express=require("express")
const router=express.Router()
module.exports=router
动态路由
app.get("/new/:id",(req,res)=>{
// 获取new后的路径
// req.params["id"]
console.log(req.params["id"]);
})
中间件
应用级中间件(用于权限判断)
app.use((req,res,next)=>{
// res.send
next() //是否继续执行
})
路由中间件(用的少)
app.get("/new/:id",(req,res,next)=>{
// 获取new后的路径
// req.params["id"]
console.log(req.params["id"]);
next()
})
错误处理中间件(放在最后)
app.use((req,res,next)=>{
res.status(404).send("404")
next() //是否继续执行
})
内置中间件
app.use(express.static("static"))
cookie
npm i cookie-parser --save
const cookieParser=require("cookie-parser")
app.use(cookieParser())
//使用 maxAge 过期时间 (毫秒)
res.cookie("name":'zzz',{maxAge:5000,httpOnly:true})
//获取
req.cookies.name
参数
maxAge :5000,//过期时间
httpOnly:true ,//true 只能后台使用, false ,前台可用
secure:true,//true加密
signed:true,//签名,加密
//要配置的时候加入参数
expires:Data,//具体时间
path:String,//cookie访问目录,正常不用(只能某一个页面也用)
//path:"/login"
//多个二级域名访问cookie aaa.xxx.com bbb.xxx.com
domain:String,// domain:".xxx.com"
加密
//要在配置中间件的时候加入加密的参数
app.use(cookieParser("xxxx"))
//设置
res.cookie("name":'zzz',{maxAge:5000,signed:true})
//获取
req.signedCookies.name
session
npm i express-session --save
const session =require("express-session")
mongodb
注:
无法安装服务
sc delete MongoDB
mongod --dbpath=E:\MongoDB\data\db --logpath=E:\MongoDB\log\MongoDB.log --install --serviceName "MongoDB"
net start MongoDB
展示启动成功
安装时候不要安装conpass(可视化工具) ,要增加path (打开bin,)路径要携带bin
常用命令
cls 清屏
mongo 连接数据库
db 查看当前数据库
show dbs 所以数据库
use 数据库名 切换数据库(创建数据库)
show collections 当前数据库下的表
db.user.insert({})(user为数据表(集合))
db.user.insert({"id":2,"price":400,"num":200})
db.user.find() //查看表中内容 (user为数据表(集合))
db.dropDatabase()//删除数据库
db.user.drop() //删除集合 (user为集合)
空数据库不展示
查找
db.user.find({"name":"hha}) //找name为hh的数据
db.user.find({"age":{$gt:22}}) //查找age大于22的记录
db.user.find({"age":{$lt:22}}) //查找age小于22的记录
db.user.find({"age":{$lte:22}}) //查找age<=22的记录
db.user.find({"age":{$gte:22}}) //查找age>=22的记录
db.user.find({"name": /mon/}) //查找name中包含mon的
db.user.find({"name": /^mon/}) //查找name中以mon的开头
db.user.find({"name": /mon$/}) //查找name中以mon的结尾
db.user.find({},{'name':1}) //只显示name
db.user.find({},{'name':1,age:1}) //只显示name 和age
db.user.find().sort({'age':1}) //根据age升序
db.user.find().sort({'age':-1}) //根据age 降序
db.user.find().limit(5) //查找前5条
db.user.find().skip(10) //查询10之后的
db.user.find().count() //总共多少条
db.user.find().skip((pageSize-1)*pageNum).limit(pageSize) //分页 pagesize pageNum
db.user.find({$or:[{"age":"22},{"age":23}]}) //找age等于22或者23的
修改
注:
不加$set为完整替换
//改修 name=hah 的性别为男
参1:/查询条件 参2:要修改的数据 参3:是否多条同时修改
db.user.updata({"name":"hah"},{$set:{"sex:"男","name":xixi},{"multi:true})
删除
//参1 :要删除的条件 参2:是这删除一条
db.user.remove({"age":12},{justOne:true})
//删除age 12 或者13
db.user.remove({$or:[{"age":12},{"age":13}]})
设置索引
db.user.getIndexes() //获取当前的索引
//设置索引,user:表 name:字段 1.升序,-1降序
db.user.ensureIndex({"name":1})
db.user.dropIndex({"name":1}) //删除
//复合索引,查询条件中必须包含到复合索引 参2:索引名字
db.user.ensureIndex({"name":1},{"age":"22"})
唯一索引
db.user.ensureIndex({"userID":1},{"unique":true})
创建管理员
1.创建
use admin
db.createUser({
user:'admin',
pwd:'123456',
roles:[{'role':'root','db':'admin'}]
})
2.修改配置
D:\myWork\tools\tools\mongooses\bin\mongod.cfg
前面有#说明没有其作用 ,不能用记事本 ,webstrom打开 ,可以hbuild ,notpdd
security:
authorization: enabled
3.重启数据库
windows +r
services.msc
4.用超级管理员连接数据库
// 方式一
mongo
use admin
db.auth('admin', '123456')
// 方式二
mongo admin -u admin -p 123456
5.添加单个数据库用户
use test // 跳转到需要添加用户的数据库
db.createUser({
user: 'fooadmin', // 用户名
pwd: '123456', // 密码
roles:[{
role: 'readWrite', // 角色
db: 'test' // 数据库名
}]
})
常见命令
show users // 查看当前库下的用户
db.dropUser('testadmin') // 删除用户
db.updateUser('admin', {pwd: '654321'}) // 修改用户密码
db.auth('admin', '654321') // 密码认证
MongoDB 数据库默认角色
数据库用户角色:read、readWrite
数据库管理角色:dbAdmin、dbOwner、userAdmin
集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager
备份恢复角色:backup、restore
所有数据库角色: readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、
dbAdminAnyDatabase
超级用户角色:root
作者:地平线0530
链接:https://www.jianshu.com/p/237a0c5ad9fa
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
聚合管道
聚合管道可以对集合中的文档进行变化和组合
实际项目中:表的关联查询,数据统计
//常见的操作
$project 增加,删除,重命名字段
$match 条件匹配。满足条件的文档进入下一阶段
$limit 限制结果的数量
$skip 跳过文档的数量
$sort 条件排序
$group 条件组合结果
$lookup 可以引入其他集合的数据(关联查询)
db.user.aggregate([
{
$lookup: {
from: "user_item",//和谁关联
localField:"id", //要关联的字段
foreignField:"id",//要关联的字段
as:"user",//放到哪里
}
}
])
db.user.aggregate([
{
$project: {name: 1, id: 1}
},
{
$match: {}
}
])
mongoose基本使用
const mongoose=require("mongoose")
// 链接数据库,数据库可以不存在,在创建第一条数据时自动创建
mongoose.connect("mongodb://localhost/test",{useMongoClient:true})
mongoose.Promise=global.Promise
// 创建一个模型,第一个参数大写,为数据库的名称,会自动生成小写复数的形式,第二参数,架构的数据格式,返回模型构造函数
var Cat=mongoose.model("Cat",{name:String})
var kitty=new Cat({
name:{
type:String,
required:true,//是否必填
default:0,默认是0
enum:[0,1],//只能是0或者1
}
})
kitty.save(()=>{
})
增
kitty.save(()=>{
})
删
Cat.remove({},(err,ret)=>{
}),//参1:条件
还有其他的
改
Cat.findByIdAndUpdate("",{},(err,ret)=>{
}),//参1 :根据要找的参数,参2:要改的东西,回调
还有其他的
查
Cat.find({},(err,data)=>{
})//第一个是查询条件,可以不写
Cat.findOne({},(err,data)=>{
})//第一个参数是查询条件,可以不写
MongoBooster
数据库格式化软件
Schema
使用Schema创建约束,为了使表中无脏数据
node操作数据库
// 引入数据库
const {MongoClient} = require('mongodb')
// 数据库地址
const url = "mongodb://localhost:27017";
// 要连接的数据库(集合)
const dbName = "user"
// 实例化
const client = new MongoClient(url, { useUnifiedTopology: true })
client.connect((err) => {
if (err) {
console.log(err);
return
}
console.log("数据库链接成功");
let db=client.db(dbName)
// 查找数据 user 表
db.collection("user").find().toArray((err, data) => {
if (err) {
console.log("查找失败");
} else {
console.log(data);
// 操作完一定要关闭
client.close();
}
})
// 增加数据
db.collection("user").insertOne({"name": "di", "id": 5, "age": 25, "code": 89}, (err, result) => {
if (err) {
console.log("增加失败");
console.log(err);
} else {
console.log("增加成功");
console.log(resove);
// 操作完一定要关闭
client.close();
}
})
// 更新数据
db.collection("user").updateOne({"name": "di"}, {$set: {"age": 85}}, (err, result) => {
if (err) {
console.log("更新失败");
console.log(err);
} else {
console.log("更新成功");
console.log(resove);
// 操作完一定要关闭
client.close();
}
})
// 删除 一条
db.collection("user").deleteOne({"name": "di"}, (err) => {
if (err) {
console.log("删除失败");
console.log(err);
} else {
console.log("删除成功");
// 操作完一定要关闭
client.close();
}
})
// 删除 多条
db.collection("user").deleteMany({"name": "di"}, (err) => {
if (err) {
console.log("删除失败");
console.log(err);
} else {
console.log("删除成功");
// 操作完一定要关闭
client.close();
}
})
})
实例化
MongoClient.connect(url,{ useUnifiedTopology: true }, (err, client) => {
if (err) {
console.log(err);
return
}
let db = client.db(dbName)
})