MongoDB——排序null处理方案

834 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情

开发过程中,有些数据可能我们需要手动排序,然而有些数据我们不需要排序,在MongoDB中我们可以增加一个字段(sort)来表示排序。但是这个字段为空,我们正序(ASC)的时候数据却排在最前面。

例如以下查询:

db.collection.find().sort({sort: 1})

得到的结果是:

null
null
1
2
3

我们期望的是:

1
2
3
null
null

这两种结果不同的是null 的位置。

原因

我们先看一下为什么会导致null 排序比较靠前?

因为MongoDB 的是非关系型数据库,在比较时,会先比较数据类型,MongoDB使用以下排序,从低到高:

  • 内部类型:MinKey
  • 空值:Null
  • 数字型:Numbersintslongsdoublesdecimals
  • 符号,字符型:SymbolString
  • 对象:Object
  • 数组:Array
  • 内置IDObjectId
  • 布尔型:Boolean
  • 日期:Date
  • 时间戳:Timestamp
  • 正则表达式:Regular Expression
  • 内部类型:MaxKey

因为 null > numbers 所以排在前面。

方案

1、调整排序方向

假如我们可以使用倒序来满足我们的需求,我们可以采取倒序排序。

db.collection.find().sort({sort: -1})

2、空值过滤

假如我们不需要返回空值,或者我们可以将非空数据查询出来然后拼接空数据。

db.collection.find({sort: {$exists: true}}).sort({sort: 1})

3、补充默认值

我们可以在插入数据的时候,给数据写入一个最大值。

或者我们可以在查询的时候通过聚合操作补充一个数据

db.collection.aggregate([
    {
      $project: {
        sort: 1, 
        s: {$ifNull: MaxValue}
      }
    }  
])

但是所有的空值,我们都给赋值了错误的数据,还需要处理。

4、增加字段

我们可以添加一个字段用来标识是否排序

db.collection.find().sort({is_sort: -1, sort: 1})

也可以添加一个反转字段,每次写入都需要将数据反转,然后查询按照反转字段查询,返回按照真实数据返回。

db.collection.find().sort({sort_inverted: -1})

MongoDB在处理空值排序,确实没有关系型那么方便。希望后续可以有优化来处理