《MongoDB入门教程》第12篇 查询结果排序

发布于:2022-12-22 ⋅ 阅读:(226) ⋅ 点赞:(0)

本篇将会介绍 MongoDB 中的游标 sort() 方法,实现查询结果的排序功能。

sort() 方法

sort() 方法可以为查询返回的文档指定指定一个显示顺序:

cursor.sort({field1: order, field2: order, ...})

sort() 方法支持多字段排序,每个字段都可以指定升序或者降序排序。

{ field: 1 } 表示按照字段的升序排序:

cursor.sort({ field: 1 })

{ field: -1} 表示按照字段的降序排序:

cursor.sort({field: -1})

下面的语法表示先按照字段 field1 的升序排序,然后再按照字段 field2 的降序排序:

cursor.sort({field1: 1, field2: -1});

相同类型的数据比较很简单,但是不同 BSON 类型的数据比较略微有些复杂。

MongoDB 使用以下从小到大的顺序比较不同的 BSON 类型:

  1. MinKey(内部类型)
  2. 空类型
  3. 数字(整数、长整数、双精度浮点数、十进制数字)
  4. 符号、字符串
  5. 对象
  6. 数组
  7. BinData
  8. ObjectId
  9. 布尔类型
  10. 日期
  11. 时间戳
  12. 正则表达式
  13. MaxKey(内部类型)

更多详细信息可以参考官方文档

sort() 示例

接下来我们将会使用以下 products 集合演示 sort() 方法的使用。

db.products.insertMany([
    { "_id" : 1, "name" : "xPhone", "price" : 799, "releaseDate" : ISODate("2011-05-14T00:00:00Z"), "spec" : { "ram" : 4, "screen" : 6.5, "cpu" : 2.66 }, "color" : [ "white", "black" ], "storage" : [ 64, 128, 256 ] },
    { "_id" : 2, "name" : "xTablet", "price" : 899, "releaseDate" : ISODate("2011-09-01T00:00:00Z"), "spec" : { "ram" : 16, "screen" : 9.5, "cpu" : 3.66 }, "color" : [ "white", "black", "purple" ], "storage" : [ 128, 256, 512 ] },
    { "_id" : 3, "name" : "SmartTablet", "price" : 899, "releaseDate" : ISODate("2015-01-14T00:00:00Z"), "spec" : { "ram" : 12, "screen" : 9.7, "cpu" : 3.66 }, "color" : [ "blue" ], "storage" : [ 16, 64, 128 ] },
    { "_id" : 4, "name" : "SmartPad", "price" : 699, "releaseDate" : ISODate("2020-05-14T00:00:00Z"), "spec" : { "ram" : 8, "screen" : 9.7, "cpu" : 1.66 }, "color" : [ "white", "orange", "gold", "gray" ], "storage" : [ 128, 256, 1024 ] },
    { "_id" : 5, "name" : "SmartPhone", "price" : 599, "releaseDate" : ISODate("2022-09-14T00:00:00Z"), "spec" : { "ram" : 4, "screen" : 9.7, "cpu" : 1.66 }, "color" : [ "white", "orange", "gold", "gray" ], "storage" : [ 128, 256 ] },
    { "_id" : 6, "name" : "xWidget", "spec" : { "ram" : 64, "screen" : 9.7, "cpu" : 3.66 }, "color" : [ "black" ], "storage" : [ 1024 ] },
    { "_id" : 7, "name" : "xReader", "price" : null, "spec" : { "ram" : 64, "screen" : 6.7, "cpu" : 3.66 }, "color" : [ "black", "white" ], "storage" : [ 128 ] }
])

示例一:单个字段排序

下面的查询返回了所有存在 price 字段的文档,返回的字段包含 _id、name 以及 price:

db.products.find({
    'price': {
        $exists: 1
    }
}, {
    name: 1,
    price: 1
})

输出结果如下:

[
  { _id: 1, name: 'xPhone', price: 799 },
  { _id: 2, name: 'xTablet', price: 899 },
  { _id: 3, name: 'SmartTablet', price: 899 },
  { _id: 4, name: 'SmartPad', price: 699 },
  { _id: 5, name: 'SmartPhone', price: 599 },
  { _id: 7, name: 'xReader', price: null }
]

如果想要按照价格从低到高对返回的结果进行排序,可以使用以下 sort() 方法:

db.products.find({
    'price': {
        $exists: 1
    }
}, {
    name: 1,
    price: 1
}).sort({
    price: 1
})

输出结果如下:

[
  { _id: 7, name: 'xReader', price: null },
  { _id: 5, name: 'SmartPhone', price: 599 },
  { _id: 4, name: 'SmartPad', price: 699 },
  { _id: 1, name: 'xPhone', price: 799 },
  { _id: 2, name: 'xTablet', price: 899 },
  { _id: 3, name: 'SmartTablet', price: 899 }
]

以上示例中,价格为空的产品排在最前面,然后依次从低到高进行排列。

如果想要按照价格从高到低进行排序,可以将 sort() 方法中的 price 字段设置为 -1:

db.products.find({
    'price': {
        $exists: 1
    }
}, {
    name: 1,
    price: 1
}).sort({
    price: -1
})

返回结果如下:

[
  { _id: 2, name: 'xTablet', price: 899 },
  { _id: 3, name: 'SmartTablet', price: 899 },
  { _id: 1, name: 'xPhone', price: 799 },
  { _id: 4, name: 'SmartPad', price: 699 },
  { _id: 5, name: 'SmartPhone', price: 599 },
  { _id: 7, name: 'xReader', price: null }
]

示例二:多个字段排序

以下示例使用 sort() 方法按照 name 和 price 字段从小到大的顺序对查询结果进行排序:

db.products.find({
    'price': {
        $exists: 1
    }
}, {
    name: 1,
    price: 1
}).sort({
    price: 1,
    name: 1
});

输出结果如下:

[
  { _id: 7, name: 'xReader', price: null },
  { _id: 5, name: 'SmartPhone', price: 599 },
  { _id: 4, name: 'SmartPad', price: 699 },
  { _id: 1, name: 'xPhone', price: 799 },
  { _id: 3, name: 'SmartTablet', price: 899 },
  { _id: 2, name: 'xTablet', price: 899 }
]

在以上示例中,sort() 方法首先按照价格进行排序,然后对价格相同的结果再按照名称进行排序。_id 为 3 和 2 的产品价格相同,都是 899;它们按照名称进行升序排列,SmartTablet 排在了 xTablet 之前。

以下示例按照价格升序、名称降序的方式对返回的产品进行排序:

db.products.find({
    'price': {
        $exists: 1
    }
}, {
    name: 1,
    price: 1
}).sort({
    price: 1,
    name: -1
})

Code language: PHP (php)
Output:

[
  { _id: 7, name: 'xReader', price: null },
  { _id: 5, name: 'SmartPhone', price: 599 },
  { _id: 4, name: 'SmartPad', price: 699 },
  { _id: 1, name: 'xPhone', price: 799 },
  { _id: 2, name: 'xTablet', price: 899 },
  { _id: 3, name: 'SmartTablet', price: 899 }
]

此时,xTable 排在了 SmartTablet 之前。

示例三:基于日期排序

以下示例按照日期字段 releaseDate 对 products 集合中的文档进行排序,查询只返回了存在 releaseDate 字段的文档,并且只返回了 _id、name 以及 releaseDate 字段:

db.products.find({
    releaseDate: {
        $exists: 1
    }

}, {
    name: 1,
    releaseDate: 1
}).sort({
    releaseDate: 1
});

查询返回的结果如下:

[
  {
    _id: 1,
    name: 'xPhone',
    releaseDate: ISODate("2011-05-14T00:00:00.000Z")
  },
  {
    _id: 2,
    name: 'xTablet',
    releaseDate: ISODate("2011-09-01T00:00:00.000Z")
  },
  {
    _id: 3,
    name: 'SmartTablet',
    releaseDate: ISODate("2015-01-14T00:00:00.000Z")
  },
  {
    _id: 4,
    name: 'SmartPad',
    releaseDate: ISODate("2020-05-14T00:00:00.000Z")
  },
  {
    _id: 5,
    name: 'SmartPhone',
    releaseDate: ISODate("2022-09-14T00:00:00.000Z")
  }
]

示例四:基于嵌入字段排序

以下示例使用嵌入式文档 spec 中的 ram 字段对产品进行排序:

db.products.find({}, {
    name: 1,
    spec: 1
}).sort({
    "spec.ram": 1
});

输出结果如下:

[
  { _id: 1, name: 'xPhone', spec: { ram: 4, screen: 6.5, cpu: 2.66 } },
  {
    _id: 5,
    name: 'SmartPhone',
    spec: { ram: 4, screen: 9.7, cpu: 1.66 }
  },
  {
    _id: 4,
    name: 'SmartPad',
    spec: { ram: 8, screen: 9.7, cpu: 1.66 }
  },
  {
    _id: 3,
    name: 'SmartTablet',
    spec: { ram: 12, screen: 9.7, cpu: 3.66 }
  },
  {
    _id: 2,
    name: 'xTablet',
    spec: { ram: 16, screen: 9.5, cpu: 3.66 }
  },
  {
    _id: 6,
    name: 'xWidget',
    spec: { ram: 64, screen: 9.7, cpu: 3.66 }
  },
  {
    _id: 7,
    name: 'xReader',
    spec: { ram: 64, screen: 6.7, cpu: 3.66 }
  }
]
本文含有隐藏内容,请 开通VIP 后查看