MongoDB 高級查詢 aggregate 聚合管道

1. MongoDB 聚合管道簡介

使用聚合管道可以對集合中的文檔進行變換和組合,常用於多表關聯查詢、數據的統計。

db.COLLECTION_NAME.aggregate() 方法用來構建和使用聚合管道,下圖是官網給的實例,可以看出來聚合管道的用法還是比較簡單的。

 

2. MongoDB Aggregation 管道操作符與表達式

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

MySQL 和 MongoDB 的聚合對比:
 
 
管道操作符作爲”,所對應的“”叫做管道表達式,如 {$match:{status:"A"}}$match 稱爲管道操作符,而 status:"A"稱爲管道表達式,每個管道表達式是一個文檔結構,它是由字段名、字段值、和一些表達式操作符組成的,常用的表達式操作符有以下這些。
 
 

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
        }
    ]
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章