nodeJs-Mongodb

MongoDB开发

第一节、数据库相关概念

什么是数据库(Data Base–DB):

存储数据的仓库,并且对数据提供统一的管理

为什么需要数据库:

  • 如果没有数据库,将数据存储在内存中,则会断电即消失
  • 如果存储在本地存储,数据必须是字符串,而且对数据量的大小也是有规定
  • 以上方式数据没有进行统一的管理,对于用户来说数据的操作很麻烦

常见的数据库分类:

关系型数据库:MySQL oracle sqlServer…

​ 适用于:中大型的系统

非关系型数据库:mongoDB,Redis

适用于:小型系统或者作为缓存系统

第二节、MongoDB的一些概念

数据库:一个系统往往对应一个数据库。【安装mongo 通过mongo可以创建多个数据库】

集合:一个数据库中往往有多个集合,每一个集合类似于数组。用于保存多个数据。【一般是某一类数据对应一个集合】

文档:一个集合中可以有多个文档,每一个文档类似于数组中的一个元素。表示特定一个数据。

ObjectId:每一个文档mongoDB会自动的生成一个唯一的不重复的ID值,这个ID称为ObjectId。

image-20221125101838701

Nvicate

  • 是一个可视化的数据库操作工具

第三节、通过node JS操作mongDB

1、创建一个基础的项目

2、通过navicat创建一个数据库与项目对应

3、创建1个集合并存储数据

  • 单击创建的数据库

  • 右键集合–新建集合–ctrl+s保存–对集合起名

  • 双击打开集合,在右侧空白右键选择添加文档

    • {
          username:"tom",
          userpass:"123456"  //JS对象语法
      }
      
    • 选中某一个文档中某个数据 按向下键 输入新的文档内容【ID不要手动输入】

4、在项目中安装mongoose[在项目上打开终端]

npm i mongoose

5、编写代码将程序与mongoDB连接【app.js】

//编写数据库连接代码
//1.引入mongoose的模块
var mongoose = require("mongoose");
//2.配置连接
const DB_URL = "mongodb://127.0.0.1:27017/movsys89";//连接地址  mongodb://IP地址:27107/数据库名
//3.连接数据库
mongoose.connect(DB_URL,{useUnifiedTopology: true, useNewUrlParser: true });
//4.设置一个连接成功的回调,用于提示连接
mongoose.connection.on("connected",function(){
   console.log("已经成功连接mongodb"+DB_URL);
});

6、编写代码操作mongodb【router文件夹中】

  • 编写一个schema对象与mongodb中集合相对应

    //1.引入mongoose
    var mongoose = require("mongoose");
    //2.编写1个集合对应的Schema对象
    var userSchema = new mongoose.Schema({
        username:String,
        usrpass:String
    });
    

    将schema对象与集合绑定

    //3.将schema与集合关联起来
    mongoose.model("userModel",userSchema,"user");  // 在系统中存储了userModel对象 这个对象其实 user集合与userSchema绑定一个对象
    

    操作集合【操作userModel】

    //4、编写代码操作userModel
    async function getAllUser(){
       let data = await mongoose.model("userModel").find({});//model方法其实是一个promise对象  其中可以完成对象集合的操作
       console.log(data);
    }
    
    getAllUser();
    

    在app.js中引入编写文件[引入的位置一定是在连接的后面]

    var usersRouter = require('./routes/users');
    

    练习:创建一个user集合并存储数据,在代码中查询所有并打印

第四节、通过mongoose框架操作mongodb

find()

作用:数据的查询

语法 : mongoose.model(“模型名称”).方法名

  //1.查询所有的电影
// let data = await mongoose.model("moviesModel").find({}); //如果是一个空对象  则表示查询所有的电影
//2.根据ID查询指定的电影(在所有的文档中去比对给定的条件  严格比对)
//let data = await mongoose.model("moviesModel").find({_id:"63805df7e15d0000fd006542"});
//查询电影名为飞驰人生的电影
//let data = await mongoose.model("moviesModel").find({title:"飞驰人生"});
//3.查询电影名称包含 飞驰的电影【模糊查询】
//let data = await mongoose.model("moviesModel").find({title:{$regex:"飞驰"},options:"$i"});
//4、查询沈腾出演的电影
// let data = await mongoose.model("moviesModel").find({actor:"刘德华"});

//5.查询定影名为飞驰人生 演员名为沈腾的电影
//let data = await mongoose.model("moviesModel").find({title:"飞驰人生",actor:"沈腾"}); //并且

//6.查询沈腾或者刘德华出演的电影
let data = await mongoose.model("moviesModel").find({$or:[{actor:"刘德华"},{actor:"沈腾"}]});//或者
console.log(data);

create()

作用:添加文档

语法:

let data = awite mongoose.model(“模型名称”).create(对象或者对象数组);

//向数据库中添加 一部电影 名字叫 战狼2 演员 吴京  描述  打打杀杀  type 动作
let data = await mongoose.model("moviesModel").create(
    [
        {
            title:"喜羊羊与灰太狼",
            actor:"喜洋洋",
            desc:"非常有意思",
            type:"爱情"
        },
        {
            title:"喜羊羊与灰太狼22",
            actor:"灰太狼",
            desc:"有意思",
            type:"动作"
        }
    ]
);
console.log(data);

//create 返回结果为当前添加的对象

deleteMany

作用:删除文档

语法:let data = awite mongoose.model(模型名称).deleteMany({条件})

注意:往往是根据指定的条件进行删除,此处的条件写法跟查询的写法一致

//数据的删除
async function moviesDeleteFunction(){
    //根据指定ID删除电影
    //let  data = await mongoose.model("moviesModel").deleteMany({_id:"63805df7e15d0000fd006542"});

    //删除名字带有飞驰的电影
    let data = await  mongoose.model("moviesModel").deleteMany(
        {
            title:{$regex:"飞驰"},
            options:"$i"
        }
        );

    //通过data 来判断是否已经删除掉
    console.log(data);
}

注意:deleteMany有1个返回对象,对象中有1个属性:deletedCount 表示删除的文档个数。【我们可以通过它来判定是否删除成功】

updateMany()

作用:用于修改文档

语法:let data = awite mongoose.model(模型名称).updateMany({条件},{新的数据})

async function moviesUpdateFunction(){
    let data = await mongoose.model("moviesModel").updateMany(
        {
            _id:"638070668293bc8770c27a5c",
        },
        {
            desc:"这不仅仅是打打杀"
        }
        );

        console.log(data);
}

updateMany返回结果中有2个属性:

modifiedCount 修改的总数

matchedCount 条件匹配的条数

第五节、MVC的编程思想

简介:

在编写项目的过程中,很多的代码都是放在一起的。导致整个项目不变于维护和排错。

使用MVC实现对象项目中不同功能的代码进行归类,不同 功能的代码放在不同的文件夹中。

实现步骤:

  • M(Model–数据模型):指的是数据定义相关的代码,如:express项目中指集合对应Schema模型
    • 在项目中创建一个文件夹(model)其中就分放置整个项目的模型相关的代码【每一个文件就对应一个Schema模型 – 取名 XXXShecma】
  • V(View-视图层):前端部分,数据的展示
    • 复用以前的router文件夹(每一个文件对应一类型的操作,取名一般取为XXXRouters)
  • C(Controller-控制器层):指整个项目的业务逻辑
    • 在项目中新增一个文件夹controllers(针对不同类型的业务创建不同的JS文件,一般取名xxxController)
  • utils:放置一些公共的代码或者与业务逻辑无关的代码。
    • 在项目中新增一个文件夹utils

实现细节

编写公共代码

1、创建utils的文件夹

  • 创建appConfig.js 编写整个项目配置相关的代码
//整个项目相关的一些配置
const DB_URL = "mongodb://127.0.0.1:27017/movsys89"; //数据库连接地址
const PORT = 8080; //项目端口号

//暴露配置信息
module.exports = {
    DB_URL,
    PORT
}
  • 创建dbUtils.js 放置跟数据库操作相关的个公共代码【数据库连接】
const {DB_URL} = require("./appConfig"); //数据库连接地址
const mongoose = require("mongoose");//mongoose框架

//数据连接的获取方法
module.exports.getConnection = function(){
    mongoose.connect(DB_URL,{useUnifiedTopology: true, useNewUrlParser: true });
    
    mongoose.connection.on("connected",function(){
        console.log("已经成功连接mongodb"+DB_URL);
     });
}

2、创建model文件夹

每一个集合对应一个model文件。

userModel.js
----
const mongoose = require("mongoose");

var userSchema = new mongoose.Schema({
    username:String,
    userpass:String
},{
    versionKey:false
});

let model = mongoose.model("userModel",userSchema,"user"); //向项目中注册名为userModel的对象 整个对象就是shecma模型											与数据库集合绑定的model 同时有一个返回值,返回值也是该model

module.exports = model;  

3、创建controller文件夹用于放置核心业务代码

针对不同类型的业务,创建不同的文件

---userController.js
//编写方法实现业务的操作 数据库操作
const userModel = require("../model/userModel"); //直接引入userModel对象 

module.exports.userReg = async function(req,resp){
    console.log(req.body);
    let {username,userpass} = req.body;
     //数据操作的代码
    //将用户名和密码添加至数据库中
    //1.判断用户是否存在
    //根据用户名查询 如果查询出来的数组长度不为0 则说明重复
    let data = await userModel.find({username});  //通过userModel调用方法  --  以前mongoose.model("模型名称") 去系统找名为userModel的对象
    if(data.length!=0){
        resp.send({code:500,msg:"注册失败,用户名被占用"})
    }else{
        //做注册操作【用户名和密码存储数据库】
        let data = await userModel.create({username,userpass});
        if(data!=null){
            resp.send({code:200,msg:'注册成功',datas:data})
        }else{
            resp.send({code:500,msg:"注册失败"});
        }
    }
}

4、在routers中配置二级路径

var express = require('express');
var router = express.Router();
const userController = require("../controller/userController");

router.post("/userReg",userController.userReg);

module.exports = router;

5、在app.js中配置一级路径

第六节、分页展示数据

什么叫做分页:如果数据量很大情况下,如果采用一页显示这样用户体验和不好,所以需要对数据进行分页展示。

怎么实现分页:

1、前端知道的数据有哪些:每页的条数(pageSize) 需要查询的页数(pageNum)

image-20221128172355891

countDocuments() :获取集合中文档的总数—计算总页数的(countDocuments/pageSize)向上取整 5/3 ---- >1.1

skip() :跳过指定的条数—skip((pagenum-1)*pageSize)

limit():查询指定的条数-- limit(pageSize)

let {pageSize,pageNum}  = req.query;

//查询指定页数的数
let data = await moviesModel.find({}).skip((pageNum-1)*pageSize).limit(pageSize); //每一个的数据
let count = await moviesModel.countDocuments();//总条数
let allpages = Math.ceil(data2.length/pageSize);//计算总页数

如果是带条件的查询,计算总页数的时候

let data2 =  await moviesModel.find({title:"AAA"});
console.log(data2.length);
let allpages = Math.ceil(data2.length/pageSize);//计算总页数

第七节、多集合关联查询

为什么会需要多集合

往往一个A集合中记录的某一类的数据,如果有其他附属的关联的信息【属于另一类信息B】,需要对该关联信息重新建立一个集合B。在A集合中创建一列数据专门用于记录(B)关联数据的ID.

比如:每一部电影有自己的信息【名称,票价,评分,描述,地址】,然后每一部电影还有演员的信息【另一类信息】【演员名字,片酬,描述,性别…】。如果直接记录在一个集中

战狼  20   8.0  好看   吴京  100W  硬汉 男
战狼2 30   9.0  一般   吴京  100W  硬汉 男

问题:造成数据的冗余【每一部电影都会记录一个演员信息,如果演员重复了则数据冗余了】

解决:将不同类型的数据抽取到不同的集合中

电影集合:记录电影相关的数据【主体是电影本身】

image-20221129111723702

演员的集合:记录演员相关的信息【主体是演员本身】

image-20221129111845345

以上集合新的问题:

电影集合跟演员集合完全没有关联,根本不知道某一部电影是由谁出演的。

解决:在电影的集合中创建1列用于记录关联的演员的信息,一般记录某个演员的_id【这一列称为外键

image-20221129112407626

实现关联查询

1、分别对每一个集合创建对应Schema模型

const mongoose = require("mongoose");

const actorShcema = new mongoose.Schema({
    aname:String,
    agender:String,
    decs:String
});

let model = mongoose.model("actorModel",actorShcema,"actor");//在内存中注册模型  名为actorModel

module.exports = model;
const mongoose = require("mongoose");
let actorModel = require("./actorModel");//引入actorModel的JS文件

const moviesSchema = new mongoose.Schema({
    title:String,
    actorId:{
        type:mongoose.SchemaTypes.ObjectId, //actorId本质类型---objecId
        ref:"actorModel" //关联的集合
    },
    type:String,
    desc:String
},{
    versionKey:false
})

//注册model
let model = mongoose.model("movieModel",moviesSchema,"movies");

module.exports = model; //暴露model对象

2、在关联的集合Shcema模型中,将关联Id属性写成

actorId:{
    	type:mongoose.SchemaTypes.ObjectId, //actorId本质类型---objecId
        ref:"actorModel" //关联的集合---前提是关联的集合一定是先注册了			             mongoose.model("actorModel",actorShcema,"actor");
},

3、查询的时候将actorId通过populate方法去将actorId最终翻译对应的关联的对象

let data  = await moviesModel.find({}).populate("actorId");

注意:关联查询并不影响条件查询和分页

 let data = await moviesModel.find({}).populate("actorId").skip(1).limit(2); 

练习:将电影信息与演员信息拆分,做关联查询

关联查询中特殊操作

1、存在多个关联集合

场景:电影集合中既关联了演员的集合,又关联了类型的集合

处理方式:跟关联一个集合处理方式一致。

const moviesSchema = new mongoose.Schema({
    title:String,
    actorId:{
        type:mongoose.SchemaTypes.ObjectId, //actorId本质类型---objecId
        ref:"actorModel" //关联的集合
    },
    type:{
        type:mongoose.SchemaTypes.ObjectId,
        ref:"typeModel"
    },
    desc:String
},{
    versionKey:false
})
 let data  = await moviesModel.find({}).populate("actorId").populate("type");

2、一对多的关联查询

场景:一部电影对应多个演员

数据库层面怎么体现一对多:

在电影集合中通过数据来记录一部电影对应多个演员image-20221129144106151

代码层面:

在关联Schema模型中通过[]表示数组

actorId:[{
    type:mongoose.SchemaTypes.ObjectId, //actorId本质类型---objecId
    ref:"actorModel" //关联的集合
}],
 let data  = await moviesModel.find({}).populate("actorId").populate("type");

3、多层嵌套查询

场景:一部电影有多个评论,但是一条评论又对应一个用户

数据库层面:

image-20221129155022920

image-20221129155116262

代码层面:

1、模型对应

image-20221129155302438

 commentsId:[{
     type:mongoose.SchemaTypes.ObjectId,
     ref:"commentsModel"
 }],

image-20221129155448393

const commentsModel = new mongoose.Schema({
    content:String,
    condate:String,
    userId:
        {
            type:mongoose.SchemaTypes.ObjectId,
            ref:"userModel"
        }
},{
    versionKey:false
})

在获取数据的时候:

let data  = await moviesModel.find({}).populate("actorId").populate("type").
populate("commentsId").populate({path:"commentsId",populate:{path:"userId"}});

总结:查询处理方式

  • 查询所有 find({})
  • 条件查询 find({条件})-- 可以多条件,但是条件的属性名与值是严格匹配
  • 模糊查询 fin({字段名:{$regex:“模糊值”}})
  • 关联
    • 一对一
    • 一对多
    • 嵌套

练习:查询某部电影所有评论信息–谁评论的

第八节、数组的操作

记录普通的数据

场景:每一部电影有多个描述

在数据库层面:数组中放String

在代码层面—数据模型:

image-20221129163417512

查询的时候跟之前一直。

数组的操作【不管记录是关联ID还是普通的数据】

1、创建

直接添加数据,数据类型与模型中的类型一致即可【模型中的数据类型跟集合对应】

image-20221129170944765

async function testArrayCreate(){
    //添加元素--其中有数组
    //案例:添加一部电影---有演员列表  描述  评论[]
    let data = await moviesModel.create({
        title:"我是添加的电影",
        actorId:["638577c37b790000b1002015","6385a94ed91b0000a4000204"],
        type:"638582607b790000b1002017",
        commentsId:[],
        desc:["我是添加的1","我是添加B"]
    });
}

2、对数组元素添加 push

//向指定ID的电影commontsID数组中添加 一个评论的ID
let data2  = await moviesModel.updateMany({
    _id:"638071fedca9764920a4ce34"
},{
    $push:{
        commentsId:[data._id] //向commentsId数组中添加1个元素
    }
});

3、删除元素 【pull】

场景:删除评论

//删除数组中的元素
//案例:删评论
//思路:页面查询电影评论的时候是可以查询到每条评论的ID
//删除:先在评论表中删除指定ID的评论信息  同时在电影commentdId数组中删除对应ID
async function testArrayPull(){
    let comid = "6385cb04cf0b8fa0dfd5c45b";
    let movid = "6385c6a8711042e0d271b865";

    let data = await commentsModel.deleteMany({
        _id:comid
    });
    console.log(data);
    let  data02 = {};
    if(data.deletedCount>0){
    data02  = await moviesModel.updateMany({
        _id:movid
    },{
        $pull:{
            commentsId:comid
        }
    });
}
if(data02.modifiedCount>0){
    //删除评论成功
}else{
    //删除评论失败
}
 // if(data02)
 console.log(data02);
}
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Node.js是一个基于Chrome V8引擎的JavaScript运行环境,可以用于开发服务器端的应用程序。Express是Node.js的一个快速、灵活和极简的Web应用程序框架。MongoDB是一个面向文档的NoSQL数据库。它将数据存储在JSON样式的文档中,具有强大的灵活性和可扩展性。 在Node.js中使用MongoDB,可以使用node-mongodb-native驱动程序。首先需要安装MongoDB,并确保其服务正在运行。然后,可以使用Monk库来实现Node.js和MongoDB的交互[2]。使用Monk,你可以使用简单的JavaScript代码来连接到MongoDB数据库,执行查询和更新操作。 下面是一个使用Monk连接到MongoDB的示例代码: ``` var mongo = require('mongodb'); var monk = require('monk'); var db = monk('localhost:27017/nodetest1'); ``` 在上述代码中,我们使用`monk`模块连接到本地的`nodetest1`数据库。 通过使用Node.js、Express和MongoDB,你可以构建强大的Web应用程序,实现数据的存储和检索功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [NodeJS+Express+MongoDB](https://blog.csdn.net/weixin_33712881/article/details/85842769)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Node.js + Express + MongoDB教程](https://blog.csdn.net/boleban/article/details/39134661)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值