欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MongoDB 高级查询 aggregate 聚合管道

程序员文章站 2022-05-08 16:10:20
...

1. MongoDB 聚合管道简介

使用聚合管道可以对集合中的文档进行变换和组合,常用于多表关联查询、数据的统计。

db.COLLECTION_NAME.aggregate() 方法用来构建和使用聚合管道,下图是官网给的实例,可以看出来聚合管道的用法还是比较简单的。

MongoDB 高级查询 aggregate 聚合管道

 

2. MongoDB Aggregation 管道操作符与表达式

常用的管道操作符有以下这些:

MongoDB 高级查询 aggregate 聚合管道

MySQL 和 MongoDB 的聚合对比:
 
MongoDB 高级查询 aggregate 聚合管道
 
管道操作符作为”,所对应的“”叫做管道表达式,如 {$match:{status:"A"}}$match 称为管道操作符,而 status:"A"称为管道表达式,每个管道表达式是一个文档结构,它是由字段名、字段值、和一些表达式操作符组成的,常用的表达式操作符有以下这些。
 
MongoDB 高级查询 aggregate 聚合管道
 

3. 模拟数据

为了说明每个管道操作符的作用,将以下面数据为参考,分别有order和order_item两个集合。

order集合里的数据

{
    "_id": ObjectId("5e6f15c1eb57cc45bde8130b"),
    "order_id": "1",
    "uid": 10,
    "trade_no": "111",
    "all_price": 100,
    "all_num": 2
}
{
    "_id": ObjectId("5e6f15cbeb57cc45bde8130c"),
    "order_id": "2",
    "uid": 7,
    "trade_no": "222",
    "all_price": 90,
    "all_num": 2
}
{
    "_id": ObjectId("5e6f15d4eb57cc45bde8130d"),
    "order_id": "3",
    "uid": 9,
    "trade_no": "333",
    "all_price": 20,
    "all_num": 6
}

order_item集合里的数据

{
    "_id": ObjectId("5e6f15dbeb57cc45bde8130e"),
    "order_id": "1",
    "title": "商品鼠标 1",
    "price": 50,
    "num": 1
}
{
    "_id": ObjectId("5e6f15e2eb57cc45bde8130f"),
    "order_id": "1",
    "title": "商品键盘 2",
    "price": 50,
    "num": 1
}
{
    "_id": ObjectId("5e6f15e8eb57cc45bde81310"),
    "order_id": "1",
    "title": "商品键盘 3",
    "price": 0,
    "num": 1
}
{
    "_id": ObjectId("5e6f15f1eb57cc45bde81311"),
    "order_id": "2",
    "title": "牛奶",
    "price": 50,
    "num": 1
}
{
    "_id": ObjectId("5e6f15faeb57cc45bde81312"),
    "order_id": "2",
    "title": "酸奶",
    "price": 40,
    "num": 1
}
{
    "_id": ObjectId("5e6f1603eb57cc45bde81313"),
    "order_id": "3",
    "title": "矿泉水",
    "price": 2,
    "num": 5
}
{
    "_id": ObjectId("5e6f160aeb57cc45bde81314"),
    "order_id": "3",
    "title": "毛巾",
    "price": 10,
    "num": 1
}

 

4. 管道操作符 $project

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

例:要求查找 order 集合,只返回文档中 trade_no all_price 字段。
 
db.order.aggregate([
    {
        $project:{ trade_no:1, all_price:1 }
    }
])

执行结果:

{ "_id" : ObjectId("5e6f15c1eb57cc45bde8130b"), "trade_no" : "111", "all_price" : 100 }

{ "_id" : ObjectId("5e6f15cbeb57cc45bde8130c"), "trade_no" : "222", "all_price" : 90 }

{ "_id" : ObjectId("5e6f15d4eb57cc45bde8130d"), "trade_no" : "333", "all_price" : 20 }

 

5. 管道操作符 $match

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

例:要求查找 order 集合,只返回文档中 trade_no all_price 字段,并只显示 all_price 大于等于90的记录。

db.order.aggregate([
    { 
        $project: { trade_no: 1, all_price: 1}
    },
    { 
        $match: {
            "all_price": {$gte: 90}
        }
    }
])

执行结果:

{ "_id" : ObjectId("5e6f15c1eb57cc45bde8130b"), "trade_no" : "111", "all_price" : 100 }

{ "_id" : ObjectId("5e6f15cbeb57cc45bde8130c"), "trade_no" : "222", "all_price" : 90 }

 

6. 管道操作符 $group

将集合中的文档进行分组,可用于统计结果。

例:统计每个订单的订单数量,按照订单号分组。

db.order_item.aggregate([
    {   
        $group: 
            {_id: "$order_id", total: {$sum: "$num"}
        }
    }
])

执行结果:

{ "_id" : "2", "total" : 2 }

{ "_id" : "3", "total" : 6 }

{ "_id" : "1", "total" : 3 }

 

7. 管道操作符 $sort 

将集合中的文档进行排序。
 
例:要求查找 order 集合,只返回文档中 trade_no all_price 字段,只显示 all_price 大于等于90的记录,并以all_price进行降序排列。
 
db.order.aggregate([
    { 
        $project: { trade_no: 1, all_price: 1}
    },
    { 
        $match: {
            "all_price": {$gte: 90}
        }
    },
    { 
        $sort: {"all_price": -1}
    }
])

执行结果:

{ "_id" : ObjectId("5e6f15c1eb57cc45bde8130b"), "trade_no" : "111", "all_price" : 100 }

{ "_id" : ObjectId("5e6f15cbeb57cc45bde8130c"), "trade_no" : "222", "all_price" : 90 }

 

8. 管道操作符 $limit

限制查询结果的数量。

例:要求查找 order 集合,只返回文档中 trade_no all_price 字段,只显示 all_price 大于等于90的记录,以all_price进行降序排列,并只显示1条记录。

db.order.aggregate([
    { 
        $project: { trade_no: 1, all_price: 1}
    },
    { 
        $match: {
            "all_price": {$gte: 90}
        }
    },
    { 
        $sort: {"all_price": -1}
    },
    { 
        $limit: 1
    }
])

执行结果:

{ "_id" : ObjectId("5e6f15c1eb57cc45bde8130b"), "trade_no" : "111", "all_price" : 100 }

 

9. 管道操作符 $skip

对查询结果跳过几条记录进行显示。

例:要求查找 order 集合,只返回文档中 trade_no all_price 字段,只显示 all_price 大于等于90的记录,以 all_price 进行降序排列,并跳过1条记录显示其结果。

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

执行结果:

{ "_id" : ObjectId("5e6f15cbeb57cc45bde8130c"), "trade_no" : "222", "all_price" : 90 }

 

10. 管道操作符 $lookup

对要查询的结果时行多表关联查询。

例:查询 order 集合,关联到order_item集合,将 order 中 order_id 与 order_item 中order_id 相同的记录显示出来,并将结果取名为 items。

db.order.aggregate([
    { 
        $lookup: { 
            from: "order_item", 
            localField: "order_id", 
            foreignField: "order_id", 
            as: "items"
        }
    }
])

执行结果:

{
    "_id": ObjectId("5e6f15c1eb57cc45bde8130b"),
    "order_id": "1",
    "uid": 10,
    "trade_no": "111",
    "all_price": 100,
    "all_num": 2,
    "items": [
        {
            "_id": ObjectId("5e6f15dbeb57cc45bde8130e"),
            "order_id": "1",
            "title": "商品鼠标 1",
            "price": 50,
            "num": 1
        },
        {
            "_id": ObjectId("5e6f15e2eb57cc45bde8130f"),
            "order_id": "1",
            "title": "商品键盘 2",
            "price": 50,
            "num": 1
        },
        {
            "_id": ObjectId("5e6f15e8eb57cc45bde81310"),
            "order_id": "1",
            "title": "商品键盘 3",
            "price": 0,
            "num": 1
        }
    ]
}
{
    "_id": ObjectId("5e6f15cbeb57cc45bde8130c"),
    "order_id": "2",
    "uid": 7,
    "trade_no": "222",
    "all_price": 90,
    "all_num": 2,
    "items": [
        {
            "_id": ObjectId("5e6f15f1eb57cc45bde81311"),
            "order_id": "2",
            "title": "牛奶",
            "price": 50,
            "num": 1
        },
        {
            "_id": ObjectId("5e6f15faeb57cc45bde81312"),
            "order_id": "2",
            "title": "酸奶",
            "price": 40,
            "num": 1
        }
    ]
}
{
    "_id": ObjectId("5e6f15d4eb57cc45bde8130d"),
    "order_id": "3",
    "uid": 9,
    "trade_no": "333",
    "all_price": 20,
    "all_num": 6,
    "items": [
        {
            "_id": ObjectId("5e6f1603eb57cc45bde81313"),
            "order_id": "3",
            "title": "矿泉水",
            "price": 2,
            "num": 5
        },
        {
            "_id": ObjectId("5e6f160aeb57cc45bde81314"),
            "order_id": "3",
            "title": "毛巾",
            "price": 10,
            "num": 1
        }
    ]
}

 

相关标签: MongoDB