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