0

0

0

修罗

站点介绍

只有了解事实才能获得真正的自由

MongoDB的高级查询aggregate聚合管道

修罗 2020-10-09 1546 0条评论 nosql

首页 / 正文

MongoDB的高级查询aggregate聚合管道

https://mongodb.net.cn/manual/aggregation/

一、MongoDB 聚合管道(Aggregation Pipeline)

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

先看下官网给的实例,感受一下聚合管道的用法。

1602253232660.png

二、MongoDB Aggregation 管道操作符与表达式

管道操作符Description
$project增加、删除、重命名字段(查询结果字段限制)
$match条件匹配。只满足条件的文档才能进入下一阶段
$limit限制结果的数量
$skip跳过文档的数量
$sort条件排序。
$group条件组合结果统计
$lookup引入其它集合的数 据 (表关联查询)

SQL 和 NOSQL 对比:

SQLNOSQL
WHERE$match
GROUP BY$group
HAVING$match
SELECT$project
ORDER BY$sort
LIMIT$limit
SUM()$sum
COUNT()$sum
join$lookup

管道表达式:管道操作符作为“键”,所对应的“值”叫做管道表达式。

例如:

{ $match: {status: "A" } }

  • $match 称为管道操作符,而 status: "A"称为管道表达式, 是管道操作符的操作数(Operand)。
  • 每个管道表达式是一个文档结构,它是由字段名、字段值、和一些表达式操作符组成的。
常用表达式操作符Description
$addToSet将文档指定字段的值去重
$max文档指定字段的最大值
$min文档指定字段的最小值
$sum文档指定字段求和
$avg文档指定字段求平均
$gt大于给定值
$lt小于给定值
$eq等于给定值

三、数据模拟

// 订单表
db.order.insert({"order_id":"1","uid":10,"trade_no":"111","all_price":100,"all_num":2})

db.order.insert({"order_id":"2","uid":7,"trade_no":"222","all_price":90,"all_num":2})

db.order.insert({"order_id":"3","uid":9,"trade_no":"333","all_price":20,"all_num":6})

// 订单中的商品
db.order_item.insert({"order_id":"1","title":"商品鼠标 1","price":50,num:1})

db.order_item.insert({"order_id":"1","title":"商品键盘 2","price":50,num:1})

db.order_item.insert({"order_id":"1","title":"商品键盘 3","price":0,num:1})

db.order_item.insert({"order_id":"2","title":"牛奶","price":50,num:1})

db.order_item.insert({"order_id":"2","title":"酸奶","price":40,num:1})

db.order_item.insert({"order_id":"3","title":"矿泉水","price":2,num:5})

db.order_item.insert({"order_id":"3","title":"毛巾","price":10,num:1})

1602254882607.png

四、$project

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

例:要求查找 order 只返回文档中 trade_noall_price 字段

# 1代表要此字段,0就是不要
db.order.aggregate([
    { 
        $project: { trade_no: 1, all_price: 1 }
    }
])

1602255148767.png

五、$match

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

# 上面结果再查all_price >= 90的记录
db.order.aggregate([
    {
        $project:{ trade_no: 1, all_price: 1 }
    }, 
    {
        $match:{"all_price": { $gte: 90 }}
    }
])

1602255358192.png

六、$group

  • 将集合中的文档(按订单编号)进行分组,可用于统计结果。
  • 统计每个订单的订单数量,按照订单号分组
#_id固定写法,这里表示按order_id分组
db.order_item.aggregate([
    {     
        $group: { _id: "$order_id", total: { $sum: "$num" } }
    }
])

1602255618989.png

七、$sort

将集合中的文档进行排序。

-1倒序,1顺序

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

1602255730417.png

八、$limit

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

1602255914866.png

九、$skip

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

1602256063217.png

十、$lookup 表关联

#订单表在订单项表有多个记录,通过order_id关联,关联查询出来的记录数组名为items
db.order.aggregate([
    {
        $lookup: {
            from: "order_item",
            localField: "order_id", foreignField: "order_id", as: "items"
        }
    }
])

结果

// 第一条
{
    "_id": ObjectId("5b743d8c2c327f8d1b360540"),
    "order_id": "1",
    "uid": 10,
    "trade_no": "111",
    "all_price": 100,
    "all_num": 2,
    "items": [
        {
            "_id": ObjectId("5b743d9c2c327f8d1b360543"),
            "order_id": "1",
            "title": "商品鼠标 1",
            "price": 50,
            "num": 1
        },
        {
            "_id": ObjectId("5b743da12c327f8d1b360544"),
            "order_id": "1",
            "title": "商品键盘 2",
            "price": 50,
            "num": 1
        },
        {
            "_id": ObjectId("5b74f457089f78dc8f0a4f3b"),
            "order_id": "1",
            "title": "商品键盘 3",
            "price": 0,
            "num": 1
        }
    ]
}
// 第二条
{
    "_id": ObjectId("5b743d902c327f8d1b360541"),
    "order_id": "2",
    "uid": 7,
    "trade_no": "222",
    "all_price": 90,
    "all_num": 2,
    "items": [
        {
            "_id": ObjectId("5b743da52c327f8d1b360545"),
            "order_id": "2",
            "title": "牛奶",
            "price": 50,
            "num": 1
        },
        {
            "_id": ObjectId("5b743da92c327f8d1b360546"),
            "order_id": "2",
            "title": "酸奶",
            "price": 40,
            "num": 1
        }
    ]
}
// 第三条
{
    "_id": ObjectId("5b743d962c327f8d1b360542"),
    "order_id": "3",
    "uid": 9,
    "trade_no": "333",
    "all_price": 20,
    "all_num": 6,
    "items": [
        {
            "_id": ObjectId("5b743dad2c327f8d1b360547"),
            "order_id": "3",
            "title": "矿泉水",
            "price": 2,
            "num": 5
        },
        {
            "_id": ObjectId("5b743dff2c327f8d1b360548"),
            "order_id": "3",
            "title": "毛巾",
            "price": 10,
            "num": 1
        }
    ]
}

上面结果再查all_price >= 90的记录

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

结果

// 第一条
{
    "_id": ObjectId("5b743d8c2c327f8d1b360540"),
    "order_id": "1",
    "uid": 10,
    "trade_no": "111",
    "all_price": 100,
    "all_num": 2,
    "items": [
        {
            "_id": ObjectId("5b743d9c2c327f8d1b360543"),
            "order_id": "1",
            "title": "商品鼠标 1",
            "price": 50,
            "num": 1
        },
        {
            "_id": ObjectId("5b743da12c327f8d1b360544"),
            "order_id": "1",
            "title": "商品键盘 2",
            "price": 50,
            "num": 1
        },
        {
            "_id": ObjectId("5b74f457089f78dc8f0a4f3b"),
            "order_id": "1",
            "title": "商品键盘 3",
            "price": 0,
            "num": 1
        }
    ]
}
// 第二条
{
    "_id": ObjectId("5b743d902c327f8d1b360541"),
    "order_id": "2",
    "uid": 7,
    "trade_no": "222",
    "all_price": 90,
    "all_num": 2,
    "items": [
        {
            "_id": ObjectId("5b743da52c327f8d1b360545"),
            "order_id": "2",
            "title": "牛奶",
            "price": 50,
            "num": 1
        },
        {
            "_id": ObjectId("5b743da92c327f8d1b360546"),
            "order_id": "2",
            "title": "酸奶",
            "price": 40,
            "num": 1
        }
    ]
}

再次对字段限制,倒序

db.order.aggregate([
    {
        $lookup:
            {
                from: "order_item",
                localField: "order_id", foreignField: "order_id", as: "items"
            }
    }, 
    {
        $project:{ trade_no:1, all_price:1,items:1 }
    }, 
    {
        $match:{"all_price":{$gte:90}}
    }, 
    {
        $sort:{"all_price":-1}
    }
])

结果

// 1
{
    "_id": ObjectId("5b743d8c2c327f8d1b360540"),
    "trade_no": "111",
    "all_price": 100,
    "items": [
        {
            "_id": ObjectId("5b743d9c2c327f8d1b360543"),
            "order_id": "1",
            "title": "商品鼠标 1",
            "price": 50,
            "num": 1
        },
        {
            "_id": ObjectId("5b743da12c327f8d1b360544"),
            "order_id": "1",
            "title": "商品键盘 2",
            "price": 50,
            "num": 1
        },
        {
            "_id": ObjectId("5b74f457089f78dc8f0a4f3b"),
            "order_id": "1",
            "title": "商 品键盘 3",
            "price": 0,
            "num": 1
        }
    ]
}
// 2
{
    "_id": ObjectId("5b743d902c327f8d1b360541"),
    "trade_no": "222",
    "all_price": 90,
    "items": [
        {
            "_id": ObjectId("5b743da52c327f8d1b360545"),
            "order_id": "2",
            "title": "牛奶",
            "price": 50,
            "num": 1
        },
        {
            "_id": ObjectId("5b743da92c327f8d1b360546"),
            "order_id": "2",
            "title": "酸奶",
            "price": 40,
            "num": 1
        }
    ]
}

评论(0)


最新评论

  • https://www.studyglobus.com/author/carroll34a5552/

    Ценники на вывоз мусора сейчас космос, любые лайфхаки по экономии в тему.

  • Richardgrold

    1xbet onlayn kazino platforması ilə vaxtınızı daha səmərəli və maraqlı keçirin. Saytın canlı kazino bölməsi istifadəçilərə fərqli bir dünya təklif edir. Burada canlı dilerli kazino oyunlarının hər bir növünü sınaqdan keçirə bilərsiniz. Krupyelərin peşəkarlığı oyunun dinamikasını və marağını artırır. Müntəzəm olaraq yenilənən oyun siyahısı cansıxıcılığa yol vermir. Hesabınızı artırmaq üçün onlarla fərqli və etibarlı üsul mövcuddur. Qazanılan pullar cəmi bir neçə dəqiqə ərzində şəxsi hesabınıza köçürülür. Aktiv fəaliyyətinizə görə fərdi bonuslar və hədiyyələr qazana bilərsiniz. Dəstək xidməti həm çat, həm də e-poçt vasitəsilə kömək göstərir. 1xbet ailəsinə qoşulun və böyük uduşlar üçün ilk addımı atın. onlayn kazino

  • 砂岩白丘

    我一直梦想, 看到你们相册那样的地方。真棒。

  • 城市地標

    我喜欢, 这里分享真实经验。你的项目 就是 属于这里的。请继续。

  • 宗教地標

    我热爱这样的想法, 去那么多国家。真的很鼓舞。

  • 觀景高地

    能感受到热爱。继续保持 感受。

  • 最佳季節

    我关注这样的资源, 写得很实在。你的网站 就是 属于这里的。加油。

  • 1

    1

  • 1

    1

  • -1' OR 2+158-158-1=0+0+0+1 or 'TKCTZnRa'='

    1

日历

2026年07月

   1234
567891011
12131415161718
19202122232425
262728293031 

文章目录

推荐关键字: Linux webpack js 算法 MongoDB laravel JAVA jquery javase redis