知识点

1 MongoDB 聚合管道(Aggregation Pipeline)
2 MongoDB Aggregation 管道操作符与表达式
3 数据模拟
4 $project
5 $match
6 $group
7 $sort
8 $limit
9 $skip
10 $lookup 表关联

MongoDB多表关联查询 聚合管道(Aggregation Pipeline)

使用聚合管道可以对集合中的文档进行变换和组合。 实际项目:表关联查询、数据的统计。
MongoDB 中使用 db.COLLECTION_NAME.aggregate([{},…]) 方法 来构建和使用聚合管道。先看下官网给的实例,感受一下聚合管道的用法。

在使用这些命令的时候,感觉,这种命令类似于封装好的, 就好像跟批量修改,批量删除一样,我想这是批量查询

  1. db.orders.aggregate([ {$match:{status:"A"}},{$group:{_id:"$cust_id",total:{$sum:"$amount"}} } ])

MongoDB管道操作符与表达式 Aggregation

SQL 和 NOSQL 对比:

管道表达式:

管道操作符作为“键”,所对应的“值”叫做管道表达式。
例如{高级查询 多表关联聚合管道 批量 - 图1match 称为管道操作符,而 status:”A”称为管道表达式,
是管道操作符的操作数(Operand)。
每个管道表达式是一个文档结构,它是由字段名、字段值、和一些表达式操作符组成的。

数据模拟

注意:这里有2张表 order order_item

  1. db.order.insert({"order_id":"1","uid":10,"trade_no":"111","all_price":100,"all_num":2})
  2. db.order.insert({"order_id":"2","uid":7,"trade_no":"222","all_price":90,"all_num":2})
  3. db.order.insert({"order_id":"3","uid":9,"trade_no":"333","all_price":20,"all_num":6})
  4. db.order_item.insert({"order_id":"1","title":"商品鼠标 1","price":50,num:1})
  5. db.order_item.insert({"order_id":"1","title":"商品键盘 2","price":50,num:1})
  6. db.order_item.insert({"order_id":"1","title":"商品键盘 3","price":0,num:1})
  7. db.order_item.insert({"order_id":"2","title":"牛奶","price":50,num:1})
  8. db.order_item.insert({"order_id":"2","title":"酸奶","price":40,num:1})
  9. db.order_item.insert({"order_id":"3","title":"矿泉水","price":2,num:5})
  10. db.order_item.insert({"order_id":"3","title":"毛巾","price":10,num:1})

image.png

$project 筛选指定(显示)的字段

修改文档的结构,可以用来重命名 . 增加或删除文档中的字段

  1. db.order.aggregate([
  2. {
  3. $project:{order_id:1,teade_on:1,all_price:1 }
  4. }
  5. ])

image.png

$match 条件

  1. db.product.aggregate([
  2. {
  3. $lookup:
  4. {
  5. from: "order",
  6. localField: "id_name",
  7. foreignField: "pid",
  8. as: "inventory_docs"
  9. }
  10. }
  11. ])

作用:
用于过滤文档,用法类似于 find() 方法中的参数

  1. db.order.aggregate([
  2. {
  3. $project: {
  4. order_id: 1,
  5. teade_on: 1,
  6. all_price: 1
  7. }
  8. },
  9. {
  10. $match: {
  11. all_price: { $gte: 90 }
  12. }
  13. }
  14. ])
  15. db.order.aggregate([ {match:{all_price:{$gte:90}}} ])

image.png
image.png

$group 分组

表示,对数据的分组
将集合中的文档进行分组,可用于统计结果
统计每个订单的订单数量,按照订单号分组

  1. db.order_item.aggregate([ { "order_id", total:{$sum:1}}} ])
  2. db.order_item.aggregate([ { "order_id", total:{price"}}} ])

image.png

$sort 排序

对集合表排序 -1 表示倒序显示
这是第一张表 order

  1. db.order.aggregate([
  2. {
  3. match:{
  4. "all_price":{ $sort: {"all_price":-1}}
  5. }
  6. ])

image.png
image.png

$limit 限制

作用,表示 限制 输出几条 可用于分页操作

  1. db.order.aggregate([
  2. {
  3. match:{"all_price":{sort:{"all_price":-1}
  4. },
  5. {
  6. $limit:1
  7. }
  8. ])
  9. db.order.aggregate([ {match:{"all_price":{sort:{"all_price":-1}}, {$limit:2} ])

image.png

$skip 跳过

跳过第几条数据

  1. db.order.aggregate([ {match:{"all_price":{sort:{"all_price":-1}}, {$skip:1} ])

image.png

$lookup 表关联

案列1:

命令:
Order是主表
Order_item是副表

  1. db.order.aggregate([
  2. {
  3. $lookup:
  4. {
  5. from: "order_item",
  6. localField: "order_id",
  7. foreignField: "order_id",
  8. as: "items"
  9. }
  10. }
  11. ])

image.png
输出结果:
image.png

案列2

命令:

  1. db.order.aggregate([
  2. {
  3. $lookup:
  4. {
  5. from: "order_item",
  6. localField: "order_id",
  7. foreignField: "order_id",
  8. as: "items"
  9. }
  10. },
  11. {
  12. gte:90
  13. }
  14. ])

输出结果:
image.png

注意: $project

因为这个 $project 表示 要 显示的字段信息
image.png
也可以这样,后面书写排序
image.png
image.png

分页数据查询倒序案列

  1. exports.getOrder = async (req, res, next) => {
  2. let { pageNo, pageSize } = req.query
  3. const userJson = dealJSON(req.userJson)
  4. let softGetDate = dealJSON(await Busin_game_order.find({ user_id: userJson._id }))
  5. if (softGetDate != '' || softGetDate != null) {
  6. const totalCount = parseInt(softGetDate.length) //获取总数据
  7. const getPage = parseInt(pageNo) - 1 //获取的页数 前端传来的 page =1 mongodb数据库 0为开始 所以要减1
  8. const getSize = parseInt(pageSize) //获取显示多少条 10
  9. const totalPage = parseInt(totalCount / pageSize)
  10. await Busin_game_order.find({ user_id: userJson._id }).skip(getPage * getSize).sort([['create_item',-1]]).limit(getSize).exec((err, data) => {
  11. if (!err) {
  12. return res.send(builder({ pageSize: getSize, pageNo: getPage <= 0 ? 1 : getPage + 1, totalCount: totalCount, totalPage: totalPage <= 0 ? 1 : totalPage, data: dealJSON(data) }))
  13. }
  14. })
  15. } else {
  16. // 返回 10条数据: pageSize 1页:pageNo 总数据200条:totalCount 总页数 10 :totalPage 具体数据
  17. return res.send(builder({ pageSize: getSize, pageNo: getPage, totalCount: totalCount, totalPage: totalPage, data: softGetDate }))
  18. }
  19. }