Nodejs+Express视频教程-2021年更新(IT营大地)_哔哩哔哩_bilibili2021 Nodejs教程 Serverless Eggjs Nestjs教程10套地址: https://www.itying.com/category-83-b0.htmlhttps://www.bilibili.com/video/BV1Gz4y1X7Uq?p=20&spm_id_from=333.1007.top_right_bar_window_history.content.click

本文前置知识点:Mongoose增删改查基础

Node.js中实现MongoDB数据库的增删改查_番大茄子的博客-CSDN博客icon-default.png?t=M3C8https://blog.csdn.net/SongD1114/article/details/124107324

一. Mongoose索引

索引是对数据库表中一列或多列值进行排序的一种结构,可以优化查询速度。

  • 若有些字段用不着,就不要给他增加索引,否则会使插入数据的速度减慢。
  • 若为一个字段设置了唯一索引,则该字段不能重复
// 定义数据集合的映射,字段名称必须与数据库保持一致
var UserSchema = mongoose.Schema({
    name: {
        type: String,
        index: true, // 普通索引
    },
    age: Number,
    sn: { // 用户绑定设备的设备号
        type: String,
        unique: true, // 唯一索引
    },
    status: {
        type: Number,
        default: 1,
    },
})

二. Mongoose两表关联查询

Mongoose聚合管道中的语法和原生MongoDB中聚合管道的语法是一样的。

先学习MongoDB聚合管道语法: 

MongoDB 索引基础、聚合管道_番大茄子的博客-CSDN博客MongoDB 索引基础、唯一索引、复合索引、聚合管道https://blog.csdn.net/SongD1114/article/details/124278058用Mongoose实现聚合管道和关联查询:

const mongoose=require('mongoose')

mongoose.connect('mongodb://127.0.0.1:27017/cms-test')

const OrderSchema=mongoose.Schema({
    order_id:String,
    uid:Number,
    trade_no:String,
    all_price:Number,
    all_num:Number
})
const Order=mongoose.model('Order',OrderSchema,'order')

const OrderItemSchema=mongoose.Schema({
    order_id:String,
    title:String,
    price:Number,
    num:Number
})
const OrderItem=mongoose.model('OrderItem',OrderItemSchema,'order_item')


// 关联查询:order表关联order_item表
// 查询order表的数据时还要查询到每个订单下的商品
// 聚合管道中的语法和原生MongoDB中聚合管道的语法是一样的
Order.aggregate([
    {
        $lookup:{
            from:"order_item",
            localField:"order_id",
            foreignField:"order_id",
            as:"items"
        }
    },
    {
        $match:{"all_price":{$gte:90}}
    }
],function(err,docs){
    if(err) return console.log(err)
    console.log(JSON.stringify(docs))
})


// 关联查询:order_item表关联order表
// 查询order_item表,找出商品名是“奶酪”的商品对应的订单号和订单的总价格
// 方法1,表关联
OrderItem.aggregate([
    {
        $lookup:{
            from:"order",
            localField:"order_id",
            foreignField:"order_id",
            as:"order_info"
        }
    },
    {
        $match:{"title":"奶酪"},
        // 若此处match用的是ObjectId应写成 $match:{_id: mongoose.Types.ObjectId('12hrej3if78y3ab8d1sc8')}
    }
],function(err,docs){
    if(err) return console.log(err)
    console.log(JSON.stringify(docs))
})
// 方法2,一个表查完再查另一个表
OrderItem.find({"title":"奶酪"},function(err,docs){
    // 考虑浅拷贝和深拷贝问题
    const order_item=JSON.parse(JSON.stringify(docs))
    const order_id=order_item[0].order_id
    Order.find({"order_id":order_id},function(err,order){
        order_item[0].order_info=order[0]
        console.log(order_item)
    })
})

三.  Mongoose多表关联查询

1. Mongoose使用聚合管道aggregate实现多表关联查询

推荐使用聚合管道实现关联查询,但只有在MongoDB 3.2以上版本可以使用聚合管道

const mongoose=require('mongoose')

mongoose.connect('mongodb://127.0.0.1:27017/cms-test')

// 文章
const ArticleSchema=new mongoose.Schema({
    title:{
        type:String,
        unique:true,
    },
    cid:{ // 分类
        type:mongoose.Schema.Types.ObjectId,
    },
    author_id:{ // 用户id
        type:mongoose.Schema.Types.ObjectId,
    },
    author_name:{
        type:String,
        default:'匿名',
    },
    description:String,
    content:String,
})
const Article=mongoose.model('Article',ArticleSchema,'articles')

// 文章分类
const ArticleCateSchema=new mongoose.Schema({
    title:{
        type:String,
        unique:true,
    },
    description:String,
    addtime:{
        type:Date
    }
})
const ArticleCate=mongoose.model('ArticleCate',ArticleCateSchema,'articlecates')

// 用户
const UserSchema=new mongoose.Schema({
    username:{
        type:String,
        unique:true,
    },
    password:String,
    name:String,
    sex:String,
    age:Number,
    tel:Number,
    status:{
        type:Number,
        default:1
    }
})
const User=mongoose.model('User',UserSchema,'users')

// 查询文章信息,并显示文章的分类以及文章的作者信息
Article.aggregate([
    {
        $lookup:{
            from:"articlecates",
            localField:"cid",
            foreignField:"_id",
            as:"cate"
        }
    },
    {
        $lookup:{
            from:"users",
            localField:"author_id",
            foreignField:"_id",
            as:"user"
        }
    },
],function(err,docs){
    if(err) return console.log(err)
    console.log(JSON.stringify(docs))
})

2. Mongoose使用populate实现多表关联查询

1. 搞清楚主键、外键

  • articlecates表的主键:_id
  • articlecates表的外键:articles表中的cid
  • users表的主键:_id
  • users表的外键:articles表中的author_id

2. 定义ref

ref 放在外键里,表示和哪个表关联。

3. 关联查询

注意:使用populate需要引入所有用到的model!!!

const mongoose=require('mongoose')

mongoose.connect('mongodb://127.0.0.1:27017/cms-test')

// 文章
const ArticleSchema=new mongoose.Schema({
    title:{
        type:String,
        unique:true,
    },
    cid:{ // 分类(外键)
        type:mongoose.Schema.Types.ObjectId,
        ref:'ArticleCate'   // cid和文章分类表的Model建立关系
    },
    author_id:{ // 用户id(外键)
        type:mongoose.Schema.Types.ObjectId,
        ref:'User'          // author_id和用户表的Model建立关系
    },
    author_name:{
        type:String,
        default:'匿名',
    },
    description:String,
    content:String,
})
const Article=mongoose.model('Article',ArticleSchema,'articles')

// 文章分类
const ArticleCateSchema=new mongoose.Schema({
    title:{
        type:String,
        unique:true,
    },
    description:String,
    addtime:{
        type:Date
    }
})
const ArticleCate=mongoose.model('ArticleCate',ArticleCateSchema,'articlecates')

// 用户
const UserSchema=new mongoose.Schema({
    username:{
        type:String,
        unique:true,
    },
    password:String,
    name:String,
    sex:String,
    age:Number,
    tel:Number,
    status:{
        type:Number,
        default:1
    }
})
const User=mongoose.model('User',UserSchema,'users')

// 文章表和分类表的关联
Article.find({}).populate('cid').exec(function(err,docs){
    console.log(docs)
})

// 文章表和分类表以及用户表的关联
Article.find({}).populate('cid').populate('author_id').exec(function(err,docs){
    console.log(docs)
})

扩展阅读:

Node.js实现服务器端通用CRUD接口_番大茄子的博客-CSDN博客icon-default.png?t=M3C8https://blog.csdn.net/SongD1114/article/details/124101324

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐