Mongoose的使用,以及表单增删改查实战

Mongoose的使用

4.1简介

Mongoose是一个对象文档模型(ODM)库,它对Node原生的MongoDB模块进行了进一步的优化封装,并提供了更多的功能。

4.2优势

1)       可以为文档创建一个模式结构(Schema)

2)       可以对模型中的对象/文档进行验证

3)       数据可以通过类型转换转换为对象模型

4)       可以使用中间件来应用业务逻辑挂钩

5)       比Node原生的MongoDB驱动更容易

4.3核心对象

4.3.1 Schema

模式(约束)对象,通过Schema可以对集合进行约束

4.3.2 Model

模型对象,相当于数据库中的集合,通过该对象可以对集合进行操作

4.3.3 Document

文档对象,它和数据库中的文档相对应,通过它可以读取文档的信息,也可以对文档进行各种操作

4.4使用

4.4.1连接数据库

npm init  先自动创建一个package.json文件

1)       下载安装Mongoose

npm i mongoose --save

2)       引入Mongoose

var mongoose = require("mongoose");

3)       连接MongoDB数据库

mongoose.connect("mongodb://ip地址:端口号/数据库名");

 

const  mongoose = require("mongoose");


//1.连接数据库
// connect 
//第一个实参是数据库地址URL
//第二个实参是配置对象
//第三个实参是连接数据库的回调参数

mongoose.connect("mongodb://localhost:27017/0318_mongoose_demo",{
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useCreateIndex:true
},function(err){
    if(err){
        console.log("连接数据库失败");
    }else{
        console.log("连接数据库成功");
    }
});


// mongoose.connection.once("open",function(err){
//     if(err){
//         console.log("连接数据库失败");
//     }else{
//         console.log("连接数据库成功");
//     }
// })

// 2.创建约束对象(Schema)
let starsSchema = new mongoose.Schema({
    name:{
        type:String,    //声明当前字段数据类型
        required:true,  //声明当前字段是否必传
        unique:true     //声明当前字段是否唯一
    },
    age:Number,
    sex:{
        type:String,
        default:"未知" //声明当前字段的默认值
    },
    roles:[String],    //声明当前字段数据类型为数组, 内部子元素的类型必须是String
    info:mongoose.Schema.Types.Mixed
})

//3.创建模型对象(Model)
//第一个实参->集合名称
//第二个实参->约束对象
let starsModel = mongoose.model('stars',starsSchema);

//4.创建文档对象
let starDocument = new starsModel({
    name:"彭于晏",
    age:18.01,
    sex:"猛男",
    roles:["唐钰小宝"],
    info:"断臂帅哥"
})

//5.将文档对象存储至数据库中,是一个promise对象
starDocument.save()
    .then(function(){
        console.log('数据添加成功!!!')
    })

即可将数据保存在mongodb中,前提是mongodb服务已启动

 

使用方式

1)       Model的方法

                  create()

                           - 创建一个或多个文档对象并添加到数据库中

                  find()

                           - 查找所有符合条件的文档,返回的是数组

                  update()

                           - 修改(替换)一个或多个

                  remove()

                           - 删除一个或多个文档

 

let mongoose = require('mongoose');

//1.连接数据库
mongoose.connect("mongodb://localhost:27017/0318_mongoose_demo",{
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useCreateIndex:true
},function(err){
    if(err){
        console.log("连接失败")
    }else{
        console.log("连接成功")
    }
})

// 2.创建约束对象(Schema)
let starsSchema = new mongoose.Schema({
    name:{
        type:String,    //声明当前字段数据类型
        required:true,  //声明当前字段是否必传
        unique:true     //声明当前字段是否唯一
    },
    age:Number,
    sex:{
        type:String,
        default:"未知" //声明当前字段的默认值
    },
    roles:[String],    //声明当前字段数据类型为数组, 内部子元素的类型必须是String
    info:mongoose.Schema.Types.Mixed
})

//3.创建模型对象(Model)
//第一个实参->集合名称
//第二个实参->约束对象
let starsModel = mongoose.model('stars',starsSchema);

//C->create ,是个promise
// starsModel.create({
//     name:"鸡你太美",
//     age:9.99,
//     sex:"男孩子",
//     roles:["NBA形象大使"],
//     info:"cxk"
// })
//     .then(function(){
//         console.log("添加成功")
//     })

//R->read
// starsModel.find({age:17.99})
//     .then(function(res){
//         console.log(res)
//     })
// starsModel.findOne({age:17.99})
//     .then(function(res){
//         console.log(res)
//     })

// U->update
// starsModel.updateMany({age:17.99},{$set:{age:37.99}})
//     .then(function(res){
//         console.log(res)
//     })
// starsModel.updateOne({age:37.99},{$set:{age:27.99}})
//     .then(function(res){
//         console.log(res)
//     })

// D->delete
// starsModel.remove({sex:"男孩子"})
//     .then(function(res){
//             console.log(res)
//         })

 

 

 

 

 

required: true 必传字段
minlength:3 字符串最小长度
maxlength: 20 字符串最大长度
min: 2 数值最小为2
max: 100 数值最大为100
enum: ['html', 'css', 'javascript', 'node.js']
trim: true 去除字符串两边的空格
validate: 自定义验证器
default: 默认值
// 引入mongoose第三方模块 用来操作数据库
const mongoose = require('mongoose');
// 数据库连接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
    // 连接成功
    .then(() => console.log('数据库连接成功'))
    // 连接失败
    .catch(err => console.log(err, '数据库连接失败'));

const postSchema = new mongoose.Schema({
    title: {
        type: String,
        // 必选字段
        required: [true, '请传入文章标题'],
        // 字符串的最小长度
        minlength: [2, '文章长度不能小于2'],
        // 字符串的最大长度
        maxlength: [5, '文章长度最大不能超过5'],
        // 去除字符串两边的空格
        trim: true
    },
    age: {
        type: Number,
        // 数字的最小范围
        min: 18,
        // 数字的最大范围
        max: 100
    },
    publishDate: {
        type: Date,
        // 默认值
        default: Date.now
    },
    category: {
        type: String,
        // 枚举 列举出当前字段可以拥有的值
        enum: {
            values: ['html', 'css', 'javascript', 'node.js'],
            message: '分类名称要在一定的范围内才可以'
        }
    },
    author: {
        type: String,
        validate: {
            validator: v => {
                // 返回布尔值
                // true 验证成功
                // false 验证失败
                // v 要验证的值
                return v && v.length > 4
            },
            // 自定义错误信息
            message: '传入的值不符合验证规则'
        }
    }
});

const Post = mongoose.model('Post', postSchema);

Post.create({title:'aa', age: 60, category: 'java', author: 'bd'})
    .then(result => console.log(result))
    .catch(error => {
        // 获取错误信息对象,数组
        const err = error.errors;
        // 循环错误信息对象
        for (var attr in err) {
            // 将错误信息打印到控制台中
            console.log(err[attr]['message']);
        }
    })

 

 

 

通常不同集合的数据之间是有关系的,例如文章信息和用户信息存储在不同集合中,但文章是某个用户发表的,要查询文章的所有信息包括发表用户,就需要用到集合关联。

使用id对集合进行关联
使用populate方法进行关联集合查询

 

 

// 引入mongoose第三方模块 用来操作数据库
const mongoose = require('mongoose');
// 数据库连接
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
    // 连接成功
    .then(() => console.log('数据库连接成功'))
    // 连接失败
    .catch(err => console.log(err, '数据库连接失败'));

// 用户集合规则
const userSchema = new mongoose.Schema({
    name: {
        type: String,
        required: true
    }
});
// 文章集合规则
const postSchema = new mongoose.Schema({
    title: {
        type: String
    },
    // Post和User集合进行关联
    author: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User'
    }
});
// 用户集合
const User = mongoose.model('User', userSchema);
// 文章集合
const Post = mongoose.model('Post', postSchema);

// 创建用户
// User.create({name: 'itheima'}).then(result => console.log(result));
// 创建文章
// Post.create({titile: '123', author: '5c0caae2c4e4081c28439791'}).then(result => console.log(result));
//联合查询
Post.find().populate('author').then(result => console.log(result))

打印结果

 

 

 

 

搭建网站服务器,实现客户端与服务器端的通信
连接数据库,创建用户集合,向集合中插入文档
当用户访问/list时,将所有用户信息查询出来
将用户信息和表格HTML进行拼接并将拼接结果响应回客户端
当用户访问/add时,呈现表单页面,并实现添加用户信息功能
当用户访问/modify时,呈现修改页面,并实现修改用户信息功能
当用户访问/delete时,实现用户删除功能

提前将这些数据导入mogodb数据库playground中的User集合中

{"_id":{"$oid":"5c09f1e5aeb04b22f8460965"},"name":"张三","age":20,"hobbies":["足球","篮球","橄榄球"],"email":"zhangsan@itcast.cn","password":"123456"}
{"_id":{"$oid":"5c09f236aeb04b22f8460967"},"name":"李四","age":10,"hobbies":["足球","篮球"],"email":"lisi@itcast.cn","password":"654321"}
{"_id":{"$oid":"5c09f267aeb04b22f8460968"},"name":"王五","age":25,"hobbies":["敲代码"],"email":"wangwu@itcast.cn","password":"123456"}
{"_id":{"$oid":"5c09f294aeb04b22f8460969"},"name":"赵六","age":50,"hobbies":["吃饭","睡觉","打豆豆"],"email":"zhaoliu@itcast.cn","password":"123456"}
{"_id":{"$oid":"5c09f2b6aeb04b22f846096a"},"name":"王二麻子","age":32,"hobbies":["吃饭"],"email":"wangermazi@itcast.cn","password":"123456"}
{"_id":{"$oid":"5c09f2d9aeb04b22f846096b"},"name":"狗蛋","age":14,"hobbies":["打豆豆"],"email":"goudan@163.com","password":"123456"}

从数据库中获取数据,然后将数据填充 到模板中,返回html给浏览器,俗称ssr渲染

app.js

// 搭建网站服务器,实现客户端与服务器端的通信
// 连接数据库,创建用户集合,向集合中插入文档
// 当用户访问/list时,将所有用户信息查询出来
//     实现路由功能
//     呈现用户列表页面
//     从数据库中查询用户信息 将用户信息展示在列表中
// 将用户信息和表格HTML进行拼接并将拼接结果响应回客户端
// 当用户访问/add时,呈现表单页面,并实现添加用户信息功能
// 当用户访问/modify时,呈现修改页面,并实现修改用户信息功能
//     修改用户信息分为两大步骤
//         1.增加页面路由 呈现页面
//             1.在点击修改按钮的时候 将用户ID传递到当前页面
//             2.从数据库中查询当前用户信息 将用户信息展示到页面中
//         2.实现用户修改功能
//             1.指定表单的提交地址以及请求方式
//             2.接受客户端传递过来的修改信息 找到用户 将用户信息更改为最新的
// 当用户访问/delete时,实现用户删除功能

const http = require('http');

const url = require('url');
const querystring = require('querystring');

require('./model/index.js');
// 导入数据库集合模块
const User = require('./model/user');



// 创建服务器
const app = http.createServer();

// 为服务器对象添加请求事件
app.on('request', async (req, res) => {
    // 请求方式
    const method = req.method;
    // 请求地址,query为路由路径?后携带的参数如id, 默认是字符串,后面加个true,转换为对象
    const { pathname, query } = url.parse(req.url, true);

    if (method == 'GET') {
        // 呈现用户列表页面
        if (pathname == '/list') {
            // 查询用户信息,返回数组
            let users = await User.find();
            // html字符串
            let list = `
                <!DOCTYPE html>
                <html lang="en">
                <head>
                    <meta charset="UTF-8">
                    <title>用户列表</title>
                    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
                </head>
                <body>
                    <div class="container">
                        <h6>
                            <a href="/add" class="btn btn-primary">添加用户</a>
                        </h6>
                        <table class="table table-striped table-bordered">
                            <tr>
                                <td>用户名</td>
                                <td>年龄</td>
                                <td>爱好</td>
                                <td>邮箱</td>
                                <td>操作</td>
                            </tr>
            `;

            // 对数据进行循环操作
            users.forEach(item => {
                list += `
                    <tr>
                        <td>${item.name}</td>
                        <td>${item.age}</td>
                        <td>
                `;

                item.hobbies.forEach(item => {
                    list += `<span>${item}</span>`;
                })

                list += `</td>
                        <td>${item.email}</td>
                        <td>
                            <a href="/remove?id=${item._id}" class="btn btn-danger btn-xs">删除</a>
                            <a href="/modify?id=${item._id}" class="btn btn-success btn-xs">修改</a>
                        </td>
                    </tr>`;
            });

            list += `
                        </table>
                    </div>
                </body>
                </html>
            `;
            // 返回一个html给浏览器
            res.end(list);
        }else if (pathname == '/add') {
            // 呈现添加用户表单页面
            let add = `
                <!DOCTYPE html>
                <html lang="en">
                <head>
                    <meta charset="UTF-8">
                    <title>用户列表</title>
                    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
                </head>
                <body>
                    <div class="container">
                        <h3>添加用户</h3>
                        <form method="post" action="/add">
                          <div class="form-group">
                            <label>用户名</label>
                            <input name="name" type="text" class="form-control" placeholder="请填写用户名">
                          </div>
                          <div class="form-group">
                            <label>密码</label>
                            <input name="password" type="password" class="form-control" placeholder="请输入密码">
                          </div>
                          <div class="form-group">
                            <label>年龄</label>
                            <input name="age" type="text" class="form-control" placeholder="请填写邮箱">
                          </div>
                          <div class="form-group">
                            <label>邮箱</label>
                            <input name="email" type="email" class="form-control" placeholder="请填写邮箱">
                          </div>
                          <div class="form-group">
                            <label>请选择爱好</label>
                            <div>
                                <label class="checkbox-inline">
                                  <input type="checkbox" value="足球" name="hobbies"> 足球
                                </label>
                                <label class="checkbox-inline">
                                  <input type="checkbox" value="篮球" name="hobbies"> 篮球
                                </label>
                                <label class="checkbox-inline">
                                  <input type="checkbox" value="橄榄球" name="hobbies"> 橄榄球
                                </label>
                                <label class="checkbox-inline">
                                  <input type="checkbox" value="敲代码" name="hobbies"> 敲代码
                                </label>
                                <label class="checkbox-inline">
                                  <input type="checkbox" value="抽烟" name="hobbies"> 抽烟
                                </label>
                                <label class="checkbox-inline">
                                  <input type="checkbox" value="喝酒" name="hobbies"> 喝酒
                                </label>
                                <label class="checkbox-inline">
                                  <input type="checkbox" value="烫头" name="hobbies"> 烫头
                                </label>
                            </div>
                          </div>
                          <button type="submit" class="btn btn-primary">添加用户</button>
                        </form>
                    </div>
                </body>
                </html>
            `;
            res.end(add)
        }else if (pathname == '/modify') {
            // 查询对应的数据
            let user = await User.findOne({_id: query.id});
            let hobbies = ['足球', '篮球', '橄榄球', '敲代码', '抽烟', '喝酒', '烫头', '吃饭', '睡觉', '打豆豆']
            console.log(user)
            // 呈现修改用户表单页面
            let modify = `
                <!DOCTYPE html>
                <html lang="en">
                <head>
                    <meta charset="UTF-8">
                    <title>用户列表</title>
                    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
                </head>
                <body>
                    <div class="container">
                        <h3>修改用户</h3>
                        <form method="post" action="/modify?id=${user._id}">
                          <div class="form-group">
                            <label>用户名</label>
                            <input value="${user.name}" name="name" type="text" class="form-control" placeholder="请填写用户名">
                          </div>
                          <div class="form-group">
                            <label>密码</label>
                            <input value="${user.password}" name="password" type="password" class="form-control" placeholder="请输入密码">
                          </div>
                          <div class="form-group">
                            <label>年龄</label>
                            <input value="${user.age}" name="age" type="text" class="form-control" placeholder="请填写邮箱">
                          </div>
                          <div class="form-group">
                            <label>邮箱</label>
                            <input value="${user.email}" name="email" type="email" class="form-control" placeholder="请填写邮箱">
                          </div>
                          <div class="form-group">
                            <label>请选择爱好</label>
                            <div>
                                
                            
            `;

            hobbies.forEach(item => {
                // 判断当前循环项在不在用户的爱好数据组,checked,选中
                let isHobby = user.hobbies.includes(item);
                if (isHobby) {
                    modify += `
                        <label class="checkbox-inline">
                          <input type="checkbox" value="${item}" name="hobbies" checked> ${item}
                        </label>
                    `
                }else {
                    modify += `
                        <label class="checkbox-inline">
                          <input type="checkbox" value="${item}" name="hobbies"> ${item}
                        </label>
                    `
                }
            })

            modify += `
                            </div>
                          </div>
                          <button type="submit" class="btn btn-primary">修改用户</button>
                        </form>
                    </div>
                </body>
                </html>
            `;
            res.end(modify)
        }else if (pathname == '/remove') {
            // res.end(query.id)
            // 通过id,删除一个
            await User.findOneAndDelete({_id: query.id});
            res.writeHead(301, {
                Location: '/list'
            });
            res.end();
        }
    }else if (method == 'POST') {
        // 用户添加功能
        if (pathname == '/add') {
            // 接受用户提交的信息
            let formData = '';
            // 接受post参数,流式接收
            req.on('data', param => {
                formData += param;
            })
            // post参数接受完毕
            req.on('end', async () => {
                // 将接收的post参数,字符串转为对象形式
                let user = querystring.parse(formData)
                // 将用户提交的信息添加到数据库中
                await User.create(user);
                // 301代表重定向
                // location 跳转地址
                res.writeHead(301, {
                    Location: '/list'
                });
                res.end();
            })
        }else if (pathname == '/modify') {
            // 接受用户提交的信息
            let formData = '';
            // 接受post参数,流式接收参数
            req.on('data', param => {
                formData += param;
            })
            // post参数接受完毕
            req.on('end', async () => {
                // 转换成对象形式
                let user = querystring.parse(formData)
                // 将用户提交的信息跟新到数据库中
                await User.updateOne({_id: query.id}, user);
                // 301代表重定向
                // location 跳转地址
                res.writeHead(301, {
                    Location: '/list'
                });
                res.end();
            })
        }
    }

});
// 监听端口
app.listen(3000);

model--》index.js, 连接数据库

const mongoose = require('mongoose');
// 数据库连接 27017是mongodb数据库的默认端口
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true })
    .then(() => console.log('数据库连接成功'))
    .catch(() => console.log('数据库连接失败'));

model-->user.js, 创建数据库集合

const mongoose = require('mongoose');
// 创建用户集合规则
const userSchema = new mongoose.Schema({
    name: {
        type: String,
        required: true,
        minlength: 2,
        maxlength: 20
    },
    age: {
        type: Number,
        min: 18,
        max: 80
    },
    password: String,
    email: String,
    hobbies: [ String ]
});

// 创建集合 返回集合构造函数
const User = mongoose.model('User', userSchema);

module.exports = User;

 

第一步(数据查询),用户地址栏输入/list路径,返回html页面给浏览器

 

 第二步(添加用户),点击添加用户按钮连接,a标签,get请求,跳转到/add, 收集好参数,点击添加用户按钮,form表单,重定向到/list,post请求,查看是否增加用户成功

 

 

第三部(修改用户),在/list,点击修改按钮,a标签,跳转到/modify, 并将用户id传递过去,填写数据后,点击修改用户按钮,form表单,post请求携带用户id参数,用户数据库根据id跟新数据,然后重定向/list,查看修改用户数据是否成功

 

 第四部分(修改用户),点击删除按钮,a标签,get请求,跳转到/remove,并携带用户id参数,数据库根据id去删除该用户,并跳转到/list,是否删除成功

总结,返回的html用字符串拼接,太麻烦,需要用到模板引擎就就简便了

 

posted @ 2020-09-02 19:14  全情海洋  阅读(1098)  评论(0编辑  收藏  举报