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

本文详细介绍MongoDB游标sort()方法,如何根据单字段或多字段进行升序或降序排序,包括日期、嵌入文档等复杂情况,并通过实例演示其在产品数据查询中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇将会介绍 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 }
  }
]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不剪发的Tony老师

为 5 个 C 币而折腰。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值