欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

大数据MongoDB之mgo驱动如何对查询结果进行排序(正序逆序多字段排序)?

程序员文章站 2022-03-21 21:10:13
...

mgo - MongoDB driver for Go,是一个连接数据库的开源工具。
我们要如何使用mgo驱动对查询结果进行排序呢?(正序逆序多字段排序)


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 的参数的。但是它做了更好的封装,让我们使用起来更为简单。