1. 程式人生 > >MongoDB管道操作符(二)

MongoDB管道操作符(二)

上篇文章中我們已經學習了MongoDB中幾個基本的管道操作符,本文我們再來看看其他的管道操作符。

本文是MongoDB系列的第十三篇文章,瞭解前面的文章有助於更好的理解本文:

$group

基本操作

$group可以用來對文件進行分組,比如我想將訂單按照城市進行分組,並統計出每個城市的訂單數量:

db.sang_collect.aggregate({$group:{_id:"$orderAddressL",count:{$sum:1}}})

我們將要分組的欄位傳遞給$group函式的_id欄位,然後每當查到一個,就給count加1,這樣就可以統計出每個城市的訂單數量。

算術操作符

通過算術操作符我們可以對分組後的文件進行求和或者求平均數。比如我想計算每個城市訂單運費總和,如下:

db.sang_collect.aggregate({$group:{_id:"$orderAddressL",totalFreight:{$sum:"$freight"}}})

先按地址分組,再求和。這裡貼出部分查詢結果,如下:

{
    "_id" : "HaiKou",
    "totalFreight" : 20.0
}
{
    "_id" : "HangZhou",
    "totalFreight" : 10.0
}

也可以計算每個城市運費的平均數,如下:

db.sang_collect.aggregate({$group:{_id:"$orderAddressL",avgFreight:{$avg:"$freight"}}})

先按地址分組,然後再計算平均數。

極值操作符

極值操作符用來獲取分組後資料集的邊緣值,比如獲取每個城市最貴的運費,如下:

db.sang_collect.aggregate({$group:{_id:"$orderAddressL",maxFreight:{$max:"$freight"}}})

查詢每個城市最便宜的運費:

db.sang_collect.aggregate({$group:{_id:"$orderAddressL",minFreight:{$min:"$freight"}}})

按城市分組之後,獲取該城市第一個運費單:

db.sang_collect.aggregate({$group:{_id:"$orderAddressL",firstFreight:{$first:"$freight"}}})

獲取分組後的最後一個運費單:

db.sang_collect.aggregate({$group:{_id:"$orderAddressL",lastFreight:{$last:"$freight"}}})

資料操作符

$addToSet可以將分組後的某一個欄位放到一個數組中,但是重複的元素將只出現一次,而且元素加入到陣列中的順序是無規律的,比如將分組後的每個城市的運費放到一個數組中,如下:

db.sang_collect.aggregate({$group:{_id:"$orderAddressL",freights:{$addToSet:"$freight"}}})

重複的freight將不會被新增進來。

$push則對重複的資料不做限制,都可以新增進來,如下:

db.sang_collect.aggregate({$group:{_id:"$orderAddressL",freights:{$push:"$freight"}}})

$unwind

$unwind用來實現對文件的拆分,可以將文件中的值拆分為單獨的文件,比如我的資料如下:

{
    "_id" : ObjectId("59f93c8b8523cfae4cf4ba86"),
    "name" : "魯迅",
    "books" : [ 
        {
            "name" : "吶喊",
            "publisher" : "花城出版社"
        }, 
        {
            "name" : "彷徨",
            "publisher" : "南海出版出"
        }
    ]
}

使用$unwind命令將其拆分為獨立文件,如下:

db.sang_books.aggregate({$unwind:"$books"})

拆分結果如下:

{
    "_id" : ObjectId("59f93c8b8523cfae4cf4ba86"),
    "name" : "魯迅",
    "books" : {
        "name" : "吶喊",
        "publisher" : "花城出版社"
    }
}
{
    "_id" : ObjectId("59f93c8b8523cfae4cf4ba86"),
    "name" : "魯迅",
    "books" : {
        "name" : "彷徨",
        "publisher" : "南海出版出"
    }
}

其他操作符

$sort操作可以對文件進行排序,如下:

db.sang_collect.aggregate({$sort:{orderAddressL:1}})

用法和我們之前介紹普通搜尋中的一致,可以按照存在的欄位排序,也可以按照重新命名的欄位排序,如下:

db.sang_collect.aggregate({$project:{oa:"$orderAddressL"}},{$sort:{oa:-1}})

1表示升序、-1表示降序。

$limit返回結果中的前n個文件,如下表示返回結果中的前三個文件:

db.sang_collect.aggregate({$project:{oa:"$orderAddressL"}},{$limit:3})

$skip表示跳過前n個文件,比如跳過前5個文件,如下:

db.sang_collect.aggregate({$project:{oa:"$orderAddressL"}},{$skip:5})

$skip的效率低,要慎用。

總結

在管道開始執行的階段儘可能過濾掉足夠多的資料,這樣做有兩個好處:1.只有從集合中直接查詢時才會使用索引,儘早執行過濾可以讓索引發揮作用;2.該過濾的資料過濾掉之後,也可以降低後面管道的執行壓力。另外,MongoDB不允許一個聚合操作佔用過多的記憶體,如果有一個聚合操作佔用了超過20%的記憶體,則會直接報錯。

好了,MongoDB中的管道操作符我們就先說到這裡,小夥伴們有問題歡迎留言討論。

參考資料:

1.《MongoDB權威指南第2版》

更多資料請關注公眾號:

在這裡插入圖片描述