分享到

簡介

在顯示或檢索資料時進行排序是大多數資料庫系統的關鍵操作,這有助於將它們與其他資料儲存機制區分開來。能夠獨立於其儲存的順序來操作各種欄位的排序、優先順序和解釋是資料庫本身及其相關查詢系統最 H 有用的功能之一。

MongoDB 提供了多種控制查詢返回資料排序方式的方法。在本指南中,我們將根據您的用例,介紹如何以多種方式對資料進行排序。我們將講解簡單排序和複合排序、如何更改排序順序,以及排序如何與其他運算子結合使用。

設定示例資料

為了演示排序的工作原理,我們將查詢 students 集合中包含的多個文件。您可以透過複製貼上以下內容來建立 students 集合並插入我們將要查詢的文件

db.students.insertMany([
{
first_name: 'Carol',
last_name: 'Apple',
dob: ISODate('2010-10-30'),
address: {
street: {
name: 'Flint Rd.',
number: '803',
},
city: 'Camden',
zip: '10832',
},
},
{
first_name: 'Spencer',
last_name: 'Burton',
dob: ISODate('2008-12-04'),
address: {
street: {
name: 'Edgecombe St.',
number: '2083b',
},
city: 'Zoofreid',
zip: '80828',
},
},
{
first_name: 'Nixie',
last_name: 'Languin',
dob: ISODate('2011-02-11'),
address: {
street: {
name: 'Kensington Ln.',
number: '33',
},
city: 'Zoofreid',
zip: '80829',
},
},
{
first_name: 'Anthony',
last_name: 'Apple',
dob: ISODate('2009-08-16'),
address: {
street: {
name: 'Flint Rd.',
number: '803',
},
city: 'Camden',
zip: '10832',
},
},
{
first_name: 'Rose',
last_name: 'Southby',
dob: ISODate('2011-03-03'),
address: {
street: {
name: 'Plainfield Dr.',
number: '4c',
},
city: 'Nambles',
zip: '38008',
},
},
{
first_name: 'Lain',
last_name: 'Singh',
dob: ISODate('2013-06-22'),
address: {
street: {
name: 'Plainfield Dr.',
number: '308',
},
city: 'Brighton',
zip: '18002',
},
},
])

插入上述文件後,繼續下一節瞭解簡單排序。

如何對單個欄位排序

在 MongoDB 中對結果進行排序的基本方法是將 .sort() 方法附加到查詢上。.sort() 方法將一個文件作為引數,指定要排序的欄位以及排序方向。

最基本的排序方法是提供一個文件,指定一個欄位,該欄位指示列名,其值為 1 表示升序排序

請注意,我們正在將一個 MongoDB 投影 作為 .find() 的第二個引數,以便只顯示某些欄位。我們還附加了 .pretty() 方法,使輸出更具可讀性。

db.students
.find(
{},
{
_id: 0,
first_name: 1,
last_name: 1,
dob: 1,
}
)
.sort({
dob: 1,
})
.pretty()

上述查詢將按學生的出生日期以預設的升序返回結果

{
"first_name" : "Spencer",
"last_name" : "Burton",
"dob" : ISODate("2008-12-04T00:00:00Z")
}
{
"first_name" : "Anthony",
"last_name" : "Apple",
"dob" : ISODate("2009-08-16T00:00:00Z")
}
{
"first_name" : "Carol",
"last_name" : "Apple",
"dob" : ISODate("2010-10-30T00:00:00Z")
}
{
"first_name" : "Nixie",
"last_name" : "Languin",
"dob" : ISODate("2011-02-11T00:00:00Z")
}
{
"first_name" : "Rose",
"last_name" : "Southby",
"dob" : ISODate("2011-03-03T00:00:00Z")
}
{
"first_name" : "Lain",
"last_name" : "Singh",
"dob" : ISODate("2013-06-22T00:00:00Z")
}

要反轉排序,請將排序列設定為 -1 而不是 1

db.students
.find(
{},
{
_id: 0,
first_name: 1,
last_name: 1,
dob: 1,
}
)
.sort({
dob: -1,
})
.pretty()
{
"first_name" : "Lain",
"last_name" : "Singh",
"dob" : ISODate("2013-06-22T00:00:00Z")
}
{
"first_name" : "Rose",
"last_name" : "Southby",
"dob" : ISODate("2011-03-03T00:00:00Z")
}
{
"first_name" : "Nixie",
"last_name" : "Languin",
"dob" : ISODate("2011-02-11T00:00:00Z")
}
{
"first_name" : "Carol",
"last_name" : "Apple",
"dob" : ISODate("2010-10-30T00:00:00Z")
}
{
"first_name" : "Anthony",
"last_name" : "Apple",
"dob" : ISODate("2009-08-16T00:00:00Z")
}
{
"first_name" : "Spencer",
"last_name" : "Burton",
"dob" : ISODate("2008-12-04T00:00:00Z")
}

如何對附加欄位排序

當主排序欄位包含重複項時,MongoDB 可以使用附加欄位來控制排序。為此,您可以在傳遞給 sort() 函式的文件中傳遞額外的欄位及其排序順序。

例如,如果按 last_namestudent 文件進行排序,我們可以根據該欄位獲得按字母順序排列的學生列表

db.students
.find(
{},
{
_id: 0,
first_name: 1,
last_name: 1,
}
)
.sort({
last_name: 1,
})
.pretty()
{ "first_name" : "Carol", "last_name" : "Apple" }
{ "first_name" : "Anthony", "last_name" : "Apple" }
{ "first_name" : "Spencer", "last_name" : "Burton" }
{ "first_name" : "Nixie", "last_name" : "Languin" }
{ "first_name" : "Lain", "last_name" : "Singh" }
{ "first_name" : "Rose", "last_name" : "Southby" }

但是,有兩個學生的姓氏都是“Apple”,並且在考慮他們的名字時,返回的順序不是按字母順序排列的。

為了解決這個問題,我們可以使用 first_name 作為次要排序欄位

db.students
.find(
{},
{
_id: 0,
first_name: 1,
last_name: 1,
}
)
.sort({
last_name: 1,
first_name: 1,
})
.pretty()
{ "first_name" : "Anthony", "last_name" : "Apple" }
{ "first_name" : "Carol", "last_name" : "Apple" }
{ "first_name" : "Spencer", "last_name" : "Burton" }
{ "first_name" : "Nixie", "last_name" : "Languin" }
{ "first_name" : "Lain", "last_name" : "Singh" }
{ "first_name" : "Rose", "last_name" : "Southby" }

在進一步指定之後,結果符合我們對姓名所期望的常規字母順序。

如何使用嵌入式文件欄位排序

MongoDB 還可以根據嵌入式文件中包含的值對結果進行排序。為此,請使用點表示法深入到嵌入式文件中的相應欄位。

例如,您可以根據學生所居住的 citystudent 資料進行排序,city 是每個文件中 address 的一個組成部分。請記住,使用點表示法時,您需要引用欄位名以確保它們被正確解釋

db.students
.find(
{},
{
_id: 0,
first_name: 1,
last_name: 1,
'address.city': 1,
}
)
.sort({
'address.city': 1,
})
.pretty()
{
"first_name" : "Lain",
"last_name" : "Singh",
"address" : {
"city" : "Brighton"
}
}
{
"first_name" : "Carol",
"last_name" : "Apple",
"address" : {
"city" : "Camden"
}
}
{
"first_name" : "Anthony",
"last_name" : "Apple",
"address" : {
"city" : "Camden"
}
}
{
"first_name" : "Rose",
"last_name" : "Southby",
"address" : {
"city" : "Nambles"
}
}
{
"first_name" : "Spencer",
"last_name" : "Burton",
"address" : {
"city" : "Zoofreid"
}
}
{
"first_name" : "Nixie",
"last_name" : "Languin",
"address" : {
"city" : "Zoofreid"
}
}

您可以將其與附加排序欄位結合使用,以確保結果完全按照您的預期排序

db.students
.find(
{},
{
_id: 0,
first_name: 1,
last_name: 1,
'address.city': 1,
'address.street': 1,
}
)
.sort({
'address.city': 1,
'address.street.name': 1,
'address.street.number': 1,
last_name: 1,
first_name: 1,
})
.pretty()

在此示例中,我們按以下欄位的順序排序

  • 城市
  • 街道名稱
  • 街道號碼
  • 姓氏
  • 名字

查詢結果如下所示

{
"first_name" : "Lain",
"last_name" : "Singh",
"address" : {
"street" : {
"name" : "Plainfield Dr.",
"number" : "308"
},
"city" : "Brighton"
}
}
{
"first_name" : "Anthony",
"last_name" : "Apple",
"address" : {
"street" : {
"name" : "Flint Rd.",
"number" : "803"
},
"city" : "Camden"
}
}
{
"first_name" : "Carol",
"last_name" : "Apple",
"address" : {
"street" : {
"name" : "Flint Rd.",
"number" : "803"
},
"city" : "Camden"
}
}
{
"first_name" : "Rose",
"last_name" : "Southby",
"address" : {
"street" : {
"name" : "Plainfield Dr.",
"number" : "4c"
},
"city" : "Nambles"
}
}
{
"first_name" : "Spencer",
"last_name" : "Burton",
"address" : {
"street" : {
"name" : "Edgecombe St.",
"number" : "2083b"
},
"city" : "Zoofreid"
}
}
{
"first_name" : "Nixie",
"last_name" : "Languin",
"address" : {
"street" : {
"name" : "Kensington Ln.",
"number" : "33"
},
"city" : "Zoofreid"
}
}

現在也是提及您用於排序的欄位*不必*是您為投影提供的欄位的子集的好時機。

例如,我們可以實現完全相同的排序,但只通過輸入返回學生姓名

db.students
.find(
{},
{
_id: 0,
first_name: 1,
last_name: 1,
}
)
.sort({
'address.city': 1,
'address.street.name': 1,
'address.street.number': 1,
last_name: 1,
first_name: 1,
})
.pretty()

查詢返回以下資料

{ "first_name" : "Lain", "last_name" : "Singh" }
{ "first_name" : "Anthony", "last_name" : "Apple" }
{ "first_name" : "Carol", "last_name" : "Apple" }
{ "first_name" : "Rose", "last_name" : "Southby" }
{ "first_name" : "Spencer", "last_name" : "Burton" }
{ "first_name" : "Nixie", "last_name" : "Languin" }

如果將結果與之前的查詢進行比較,您可以驗證文件已按相同的順序返回。

結論

在本文中,我們探討了如何使用 sort() 方法來控制 MongoDB 對其查詢結果的排序方式。我們涵蓋了單欄位排序、按優先順序對多個欄位排序、更改排序順序以及基於嵌入式文件欄位進行排序。

結合文件排序規則結果限制等功能,排序使您能夠精確控制文件和欄位如何相互比較以及如何返回。熟悉這些功能可以幫助您編寫更好的查詢,並以更接近您使用方式的狀態返回資料。

關於作者
Justin Ellingwood

Justin Ellingwood

Justin 自 2013 年以來一直撰寫有關資料庫、Linux、基礎設施和開發者工具的文章。他目前與妻子和兩隻兔子住在柏林。他通常不必以第三人稱寫作,這對所有相關方來說都是一種解脫。
© . This site is unofficial and not affiliated with Prisma Data, Inc.