mongoose 操作记录

121 阅读1分钟

同步数量加 1 操作

// 增加文章分类的 articleCount 计数
module.exports.addNumCategory = async (_id) => {
  return await CategoryModel.updateOne(
    { _id }, // 查询条件
    { $inc: { articleCount: 1 } }, // 使用 $inc 让 articleCount +1
  )
}

分页查询操作

// 分页查询 分类
module.exports.getCategoryAll = async (pageNum, pageSize) => {
  const list = await CategoryModel.find()
    .skip((pageNum - 1) * pageSize)
    .limit(pageSize)
    .sort({ order: -1 })

  const total = await CategoryModel.countDocuments()

  return {
    list,
    total,
    pageNum,
    pageSize,
  }
}

聚合查询 关联表查询

// 用户发表的游记 链表查询  游记表 关联 用户表 查询
module.exports.getArticleByUser = async (pageNum, pageSize) => {
  const list = await ArticleModel.aggregate([
    // 跳过前面的记录,实现分页
    { $skip: (pageNum - 1) * pageSize },
    // 限制返回条数,实现分页
    { $limit: pageSize },
    // 按时间戳倒序排序
    { $sort: { time_stamp: -1 } },
    // 通过 author_uid 关联用户表
    {
      $lookup: {
        from: UserModel.collection.name, // 关联的集合名
        localField: 'author_uid', // 游记表字段
        foreignField: 'uid', // 用户表字段
        as: 'author_data' // 结果放入 author_data(数组)
      }
    },
    // 展平 author_data 数组,将其变成对象(一篇游记只对应一个作者情况下可进行展开)
    { $unwind: '$author_data' },
    // 控制返回的字段
    {
      $project: {
        _id: 1, // 游记 ID
        title: 1, // 游记标题
        address: 1, // 地址信息
        time: 1, // 游记时间
        'author_data.nickname': 1 // 作者昵称
      }
    }
  ])

模糊查询地址 例子

// 聚合查询地址,也就是根据关键字模糊匹配省份或城市名
module.exports.searchAddressAg = async (keyword) => {
  // 创建正则表达式,忽略大小写
  const regex = new RegExp(keyword, 'i')

  // 使用 MongoDB 的 aggregate 聚合查询
  const res = await AddressModel.aggregate([
    {
      // 第一阶段:筛选出省名或城市名中含有关键字的数据
      $match: {
        $or: [
          { provinceName: regex }, // 省名称匹配关键字
          { 'citys.cityName': regex } // 城市名称匹配关键字
        ]
      }
    },
    {
      // 第二阶段:投影(即指定返回的数据结构)
      $project: {
        _id: 0, // 不返回 _id 字段
        provinceName: 1, // 返回 provinceName 字段
        citys: {
          // 使用 $filter 过滤城市列表中匹配的城市
          $filter: {
            input: '$citys', // 要过滤的字段(城市数组)
            as: 'city', // 每一项的变量名叫 city
            cond: {
              // 过滤条件:城市名或省名匹配关键字
              $or: [
                { $regexMatch: { input: '$$city.cityName', regex } }, // 匹配城市名
                { $regexMatch: { input: '$provinceName', regex } } // 匹配省名(其实上面 $match 已经匹配过)
              ]
            }
          }
        }
      }
    }
  ])

  return res
}

lean() 表示返回的是 普通 json 数据 只用于返回前端展示 不做操作

module.exports.getUserById = async (uid) => {
  return await UserModel.find({ uid }, { _id: true }).lean()
}

联表查询的第二种方式(非聚合)

// 获取所有用户列表数据
module.exports.getUserAllList = async () => {
  return await UserModel.find()
    .select({
      _id: 0, // 0 表示不返回 1表示返回
      experience: 0,
    })
    .populate({ // 关联查询 角色表
      path: 'role',
      select: '-createAt -updateAt -permissions -_id', // 表示 不返回的 字段
    })
    .lean()
}

分页查询 带关键字查询以及分类id查询

// 分页查询文章博客
module.exports.getArticleList = async (pageNum, pageSize, keyword, category) => {
  const matchCondition = {}
  // 如果传入了 keyword 就在 title 和 desc 里面查询
  if (keyword) {
    matchCondition.$or = [
      { title: { $regex: keyword, $options: 'i' } }, //不区分大小写匹配 标题
      { description: { $regex: keyword, $options: 'i' } }, //不区分大小写匹配 描述
    ]
  }

  // 如果传入了 分类 id
  if (category) {
    matchCondition.category = new mongoose.Types.ObjectId(category + '') // 转成 mongodb 识别的 ObjectId 类型
  }

  const list = await ArticleModel.aggregate([
    { $match: matchCondition },
    { $skip: (pageNum - 1) * pageSize },
    { $limit: pageSize },
    { $sort: { time_stamp: -1 } },
    {
      $lookup: {
        from: CategoryModel.collection.name,
        localField: 'category',
        foreignField: '_id',
        as: 'category_data',
      },
    },
    {
      $unwind: '$category_data',
    },
  ])

  const total = await ArticleModel.countDocuments()

  return {
    list,
    total,
    pageNum,
    pageSize,
  }
}