005.MongoDB索引及聚合

木二發表於2019-06-05

一 MongoDB 索引

索引通常能夠極大的提高查詢的效率,如果沒有索引,MongoDB在讀取資料時必須掃描集合中的每個檔案並選取那些符合查詢條件的記錄。
這種掃描全集合的查詢效率是非常低的,特別在處理大量的資料時,查詢可以要花費幾十秒甚至幾分鐘,這對網站的效能是非常致命的。
索引是特殊的資料結構,索引儲存在一個易於遍歷讀取的資料集合中,索引是對資料庫表中一列或多列的值進行排序的一種結構。

1.1 createIndex() 方法

MongoDB使用 createIndex() 方法來建立索引。
語法格式:
  1 > db.collection.createIndex(keys, options)
引數說明:
  • Key :key值為你要建立的索引欄位;
  • options:options為1 表示按升序建立索引,為-1表示按降序來建立索引。
  1 [root@uhost ~]# mongo --host 172.24.9.225 --port 27017 -u useradmin -p useradmin
  2 > use mydb
  3 > db.age01.createIndex({age: 1})
  4 {
  5         "createdCollectionAutomatically" : false,
  6         "numIndexesBefore" : 1,
  7         "numIndexesAfter" : 2,
  8         "ok" : 1
  9 }
 
createIndex() 方法中你也可以設定使用多個欄位建立索引(關係型資料庫中稱作複合索引)。
  1 > db.age01.createIndex({age: 1, tel: -1})
  2 {
  3         "createdCollectionAutomatically" : false,
  4         "numIndexesBefore" : 2,
  5         "numIndexesAfter" : 3,
  6         "ok" : 1
  7 }
 

1.2 createIndex() 可選引數

可選引數列表如下:
Parameter
Type
Description
background
Boolean
建索引過程會阻塞其它資料庫操作,background可指定以後臺方式建立索引,即增加 "background" 可選引數。 "background" 預設值為false。
unique
Boolean
建立的索引是否唯一。指定為true建立唯一索引。預設值為false.
name
string
索引的名稱。如果未指定,MongoDB的通過連線索引的欄位名和排序順序生成一個索引名稱。
sparse
Boolean
對文件中不存在的欄位資料不啟用索引;這個引數需要特別注意,如果設定為true的話,在索引欄位中不會查詢出不包含對應欄位的文件.。預設值為 false.
expireAfterSeconds
integer
指定一個以秒為單位的數值,完成 TTL設定,設定集合的生存時間。
v
index version
索引的版本號。預設的索引版本取決於mongod建立索引時執行的版本。
weights
document
索引權重值,數值在 1 到 99,999 之間,表示該索引相對於其他索引欄位的得分權重。
default_language
string
對於文字索引,該引數決定了停用詞及詞幹和詞器的規則的列表。 預設為英語
language_override
string
對於文字索引,該引數指定了包含在文件中的欄位名,語言覆蓋預設的language,預設值為 language.
  1 > db.age01.createIndex({age: 1, tel: -1},{background: 'true'})
  2 {
  3         "numIndexesBefore" : 3,
  4         "numIndexesAfter" : 3,
  5         "note" : "all indexes already exist",
  6         "ok" : 1
  7 }
 

1.3 檢視索引

  1 > db.age01.getIndexes()

1.4 檢視集合索引大小

  1 > db.age01.totalIndexSize()

1.5 刪除指定集合

  1 > db.age01.dropIndex('age_1_tel_-1')
  2 { "nIndexesWas" : 3, "ok" : 1 }
 

1.6 刪除所有索引

  1 > db.age01.dropIndexes()
  2 {
  3         "nIndexesWas" : 2,
  4         "msg" : "non-_id indexes dropped for collection",
  5         "ok" : 1
  6 }
 

二 MongoDB聚合

2.1 aggregate() 方法

MongoDB中聚合(aggregate)主要用於處理資料(諸如統計平均值,求和等),並返回計算後的資料結果。有點類似sql語句中的 count(*)。
MongoDB中聚合的方法使用aggregate()。
語法格式:
  1 > db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
  2 [root@uhost ~]# mongo --host 172.24.9.225 --port 27017 -u useradmin -p useradmin
  3 > use mydb
  4 > db.age01.aggregate([{$group: {_id: "$tel", tel: {$sum: 1}}}])
  5 { "_id" : "123456784", "tel" : 1 }
  6 { "_id" : "188888888", "tel" : 2 }
  7 { "_id" : "155555555", "tel" : 1 }
 
提示:以上操作為統計所有各個tel的個數,類似select tel count(*) from age01 group by tel。

2.2 聚合表示式

表示式
描述
例項
$sum
計算總和。
db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}])
$avg
計算平均值
db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}])
$min
獲取集合中所有文件對應值得最小值。
db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}])
$max
獲取集合中所有文件對應值得最大值。
db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}])
$push
在結果文件中插入值到一個陣列中。
db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}])
$addToSet
在結果文件中插入值到一個陣列中,但不建立副本。
db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}])
$first
根據資源文件的排序獲取第一個文件資料。
db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}])
$last
根據資源文件的排序獲取最後一個文件資料
db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}])

三 管道

3.1 管道的概念

管道在Unix和Linux中一般用於將當前命令的輸出結果作為下一個命令的引數。
MongoDB的聚合管道將MongoDB文件在一個管道處理完畢後將結果傳遞給下一個管道處理。管道操作是可以重複的。
表示式:處理輸入文件並輸出。表示式是無狀態的,只能用於計算當前聚合管道的文件,不能處理其它的文件。
聚合框架常用操作:
  • $project:修改輸入文件的結構。可以用來重新命名、增加或刪除域,也可以用於建立計算結果以及巢狀文件。
  • $match:用於過濾資料,只輸出符合條件的文件。$match使用MongoDB的標準查詢操作。
  • $limit:用來限制MongoDB聚合管道返回的文件數。
  • $skip:在聚合管道中跳過指定數量的文件,並返回餘下的文件。
  • $unwind:將文件中的某一個陣列型別欄位拆分成多條,每條包含陣列中的一個值。
  • $group:將集合中的文件分組,可用於統計結果。
  • $sort:將輸入文件排序後輸出。
  • $geoNear:輸出接近某一地理位置的有序文件。
  1 [root@uhost ~]# mongo --host 172.24.9.225 --port 27017 -u useradmin -p useradmin
  2 > use mydb
  3 > db.age01.aggregate({$project: {name: 1, tel: 1,}}).pretty()
 
001
提示:_id預設為輸出,可通過_id: 0關閉_id的輸出。
  1 > db.age01.aggregate([{$match : {age: {$gt: '10', $lt: '20'}}},{$group: {_id: null, count: {$sum: 1}}}])
  2 { "_id" : null, "count" : 2 }			#$match過濾出符合條件的資料,然後$group進行再次處理。
 

3.2 時間聚合

  1 db.getCollection('m_msg_tb').aggregate(
  2 [
  3     {$match:{m_id:10001,mark_time:{$gt:new Date(2017,8,0)}}},
  4     {$group: {
  5        _id: {$dayOfMonth:'$mark_time'},
  6         pv: {$sum: 1}
  7         }
  8     },
  9     {$sort: {"_id": 1}}
 10 ])
 
時間關鍵字如下:
  • $dayOfYear: 返回該日期是這一年的第幾天(全年 366 天)。
  • $dayOfMonth: 返回該日期是這一個月的第幾天(1到31)。
  • $dayOfWeek: 返回的是這個周的星期幾(1:星期日,7:星期六)。
  • $year: 返回該日期的年份部分。
  • $month: 返回該日期的月份部分( 1 到 12)。
  • $week: 返回該日期是所在年的第幾個星期( 0 到 53)。
  • $hour: 返回該日期的小時部分。
  • $minute: 返回該日期的分鐘部分。
  • $second: 返回該日期的秒部分(以0到59之間的數字形式返回日期的第二部分,但可以是60來計算閏秒)。
  • $millisecond:返回該日期的毫秒部分( 0 到 999)。
  • $dateToString: { $dateToString: { format: , date: } }。

相關文章