大資料MongoDB之mgo驅動如何對查詢結果進行排序(正序逆序多欄位排序)?

RunFromHere發表於2019-03-20

mgo - MongoDB driver for Go,是一個連線資料庫的開源工具。
我們要如何使用mgo驅動對查詢結果進行排序呢?(正序逆序多欄位排序)

文章目錄

  1.Sort() 方法
    1.1 可以使用 Sort() 方法根據某個欄位進行排序
    1.2 可以逆序查詢,只要在欄位名前加上 '-' 號就好
    1.3 也可以多欄位查詢
  2.原始碼解析


1.Sort() 方法

1.1 可以使用 Sort() 方法根據某個欄位進行排序

query1 := collection.Find(nil).Sort("name")
複製程式碼

結果示例

name time
Caochao 2019
Caochao 2017
Caochao 2018
Liubei 2018
Liubei 2017
Sunquan 2019
Sunquan 2018

Sort() 方法會接收你傳入的某個欄位,然後向資料庫傳送排序請求,再接收資料庫返回的結果。



1.2 可以逆序查詢,只要在欄位名前加上 '-' 號就好

query2 := collection.Find(nil).Sort("-name")
複製程式碼

結果示例

name time
Sunquan 2018
Sunquan 2019
Liubei 2017
Liubei 2018
Caochao 2018
Caochao 2017
Caochao 2019



1.3 也可以多欄位查詢

欄位在前的則是優先排序的,欄位在後的就進行二級排序

像下面的就是先根據名稱進行排序,再根據時間進行排序。

query1 := collection.Find(nil).Sort("name", "time")
複製程式碼

結果示例

name time
Caochao 2017
Caochao 2018
Caochao 2019
Liubei 2017
Liubei 2018
Sunquan 2018
Sunquan 2019

2. 原始碼解析

MongoDB傳參的方式是使用引數 1 與 -1 來指定的,如 db.COLLECTION_NAME.find().sort({KEY:1}) 就是根據key欄位進行正序排序。而mgo是通過在欄位名前加上 '+'-' 符號實現正反排序的操作的,跟我們所熟悉的MongoDB的操作方式不太一樣。 mgo是怎麼用 '-' 實現正反序這樣的效果的?

我們可以看看原始碼

func (q *Query) Sort(fields ...string) *Query {
   q.m.Lock()
   var order bson.D
   for _, field := range fields {
      n := 1
      var kind string
      if field != "" {
         if field[0] == '$' {
            if c := strings.Index(field, ":"); c > 1 && c < len(field)-1 {
               kind = field[1:c]
               field = field[c+1:]
            }
         }
         switch field[0] {
         case '+':
            field = field[1:]
         case '-':
            n = -1
            field = field[1:]
         }
      }
      if field == "" {
         panic("Sort: empty field name")
      }
      if kind == "textScore" {
         order = append(order, bson.DocElem{Name: field, Value: bson.M{"$meta": kind}})
      } else {
         order = append(order, bson.DocElem{Name: field, Value: n})
      }
   }
   q.op.options.OrderBy = order
   q.op.hasOptions = true
   q.m.Unlock()
   return q
}
複製程式碼

下面是一些關鍵點,我挑出來給大家看一下

n := 1

switch field[0] {
case '+':
    field = field[1:]
case '-':
    n = -1
    field = field[1:]
}

order = append(order, bson.DocElem{Name: field, Value: n})
複製程式碼

他先是預設按照正序排序( n := 1 ),再對傳進來的欄位名進行篩選。如果欄位名前面帶有 '-',則識別為逆序排序,最後帶上引數 n 向MongoDB傳送請求。

從這些關鍵地方我們可以知道,mgo的底層操作其實也是傳 1 與 -1 的引數的。但是它做了更好的封裝,讓我們使用起來更為簡單。

相關文章