• 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用字符串拼接,太麻烦,需要用到模板引擎就就简便了

  • 相关阅读:
    10分钟学会在Ubuntu 18.04 LTS上安装NFS服务器和客户端
    脱发、秃头防不胜防?这里有一份给码农的减压指南 [转自机器之心]
    Ubuntu通过apt-get安装指定版本和查询软件源有多少个版本
    ubuntu tree 查看目录结构
    Clion快捷键
    斜杠与反斜杠的记法
    C++ 既有约定
    docker其他参考资料
    标准错误重定向、标准输入重定向
    第一本Docker书读书笔记
  • 原文地址:https://www.cnblogs.com/fsg6/p/13603508.html
Copyright © 2020-2023  润新知