对 Atlas Search 结果进行排序
在此页面上
Overview
Atlas Search 允许您在 Atlas Search 索引中定义的字段中,按升序或降序对结果进行排序。您可以使用 sort
选项按以下字段类型进行排序:
boolean
date
number
(整数、浮点数和 double 值)objectId
uuid
string
(索引为 词元类型)
您还可以按结果中文档的分数和 空值进行排序。
使用
要对 Atlas Search 结果进行排序,必须执行以下步骤:
行为
按布尔值、日期、数值、UUID、ObjectId 或字符串字段排序
sort
选项采用一个文档,该文档指定要作为排序依据的字段以及相应的排序顺序。对于支持的数据类型,Atlas Search 遵循 MongoDB 比较顺序。它像 BinData
一样处理 UUID 值。要了解更多信息,请参阅不存在的字段。
您可以指定以下排序顺序来对结果进行排序:
| 按升序排序。 当您按升序排序时,Atlas Search 将先返回值缺失的文档,然后再返回包含值的文档。 |
| 按降序排序。 |
按分数和唯一字段排序
您还可以按分数升序或降序排序。 sort
选项采用指定$meta表达式的文档,该表达式需要searchScore
值。
例子
假设您的应用程序支持用户跳到搜索结果的最后一页。以下示例按分数升序对结果进行排序,以便分数最低的文档显示在结果的顶部:
sort: {score: {$meta: "searchScore", order: 1}}
当结果中的多个文档具有相同分数时,您还可以使用 sort
确保结果具有确定的顺序。例如,如果您按唯一字段(例如名为 lastUpdated
的日期字段,如下例所示)对结果进行排序,Atlas Search 将按确定的顺序返回分数相同的结果:
例子
sort: {score: {$meta: "searchScore"}, lastUpdated: 1}
但是,如果不指定唯一字段对结果进行排序,Atlas Search 返回的结果将按分数降序排序。Atlas Search 以任意顺序返回具有相同分数或值的结果。以下示例不按唯一字段对结果进行排序。
例子
sort: {score: {$meta: "searchScore"}}
要了解详情,请参阅对结果中的文档进行评分。
数组排序
Atlas Search 将数组展平以进行排序。
例子
请考虑以下数组:
[4, [1, [8,5], 9], 2]
Atlas Search 将前面的数组展平,类似于以下内容:
4, 1, 8, 5, 9, 2
对于升序排序,Atlas Search 使用 1
将数组与其他值进行比较。对于降序排序,Atlas Search 使用 9
将数组与其他值进行比较。
与数组内的元素进行比较时:
对于升序排序,Atlas Search 比较数组的最小元素,或执行小于 (
<
) 比较。例子
如果按编号升序排序,Atlas Search 会按以下顺序排列结果:
-20 [-3, 12] // <- -3 comes before 5. 5 [6, 18] // <- 6 comes after 5. 13 14 对于降序排序,Atlas Search 比较数组的最大元素,或执行大于 (
>
) 比较。例子
如果按数字降序排序,Atlas Search 会按以下顺序对结果进行排序:
[6, 18] // <- 18 comes before 14. 14 13 [-3, 12] // <- 12 comes after 13. 5 -20
对多种类型的数组进行排序
对包含多个 BSON 类型值的大量字段进行排序时, Atlas Search会根据MongoDB的默认比较和排序顺序,从大量中选择一个有代表性的元素进行比较。
对于升序排序, Atlas Search使用具有最低BSON类型的元素。
对于降序排序, Atlas Search使用具有最高BSON类型的元素。
如果大量中有多个相同BSON类型的值,则应用所选类型的标准排序行为。
例子
请考虑以下数组:
[ 'foo', null, 15, true, false ]
对于降序排序, Atlas Search使用
true
,因为它是大量中最高的BSON类型,并且Atlas Search将true
值排在false
值之上。
但是,如果您在noData: highest
sort
语法中设立 , Atlas Search会将 null 值和缺失值视为最高BSON类型。对于示例大量,以下行为适用:
对于升序排序, Atlas Search使用
15
,因为它现在是大量中最低的BSON类型。对于降序排序, Atlas Search使用
null
,因为它现在是大量中最高的BSON类型。
按 Null 和缺失值排序
Atlas Search将 null 值视为等于缺失值和空值,并且在排序时,具有这些值的文档的顺序是不确定的。
默认, Atlas Search遵循MongoDB比较和排序顺序,并将空值视为低于所有其他支持的BSON 类型。因此,升序排序时,空值出现在结果的顶部;降序排序时,空值出现在结果的底部。
要配置 null 值在结果中出现的位置,请在noData
sort
语法中指定 字段。noData
字段采用以下值:
lowest
(默认):在排序期间将空值设置为最低的BSON类型。升序排序时,将空值排序在结果的顶部;降序排序时,将空值排序在结果的底部。highest
:在排序期间将 null 值设置为最高BSON类型。在升序排序期间,将空值排序在结果的底部;在降序排序时,将空值排序在顶部。
对嵌入式文档数组字段进行排序
要按嵌入式文档字段对父文档进行排序,必须执行以下操作:
Atlas Search 仅对父文档进行排序。 它不会对文档数组中的子字段进行排序。 有关示例,请参阅排序示例。
Considerations
一致性(Consistency)
Atlas Search 索引最终是一致的,结果中返回的值可能与排序时使用的值不同。
性能
此功能可优化使用 $search
和 $limit
作为后续阶段的查询。如果 Atlas Search 需要对集合中的所有文档进行排序,响应可能会很慢。
评分
Atlas Search 返回结果中所有文档的分数。但是,您可能会在得分较低的文档之后看到得分较高的文档,因为结果中文档的顺序是基于排序条件,除非您明确要求按分数排序。
限制
不能对 embeddedDocuments 类型的字段进行排序。
不能将
sort
选项与已弃用的 knnBeta 操作符一起使用。
兼容性
Atlas 支持在 MongoDB 5.0 的所有主要和次要版本及更高版本上使用非分片排序查询。分片排序查询可在 6.0 的所有主要版本以及 7.0 和更高版本的所有主要和次要版本上使用。如果您在运行 MongoDB v5.0 及更早版本的分片 Atlas 集群上使用 sort
,Atlas Search 将返回错误。
语法
sort
通过以下语法实现:
1 { 2 "$search": { 3 "index": "<index name>", // optional, defaults to "default" 4 "<operator>": { // such as "text", "compound", or "phrase" 5 <operator-specification> 6 }, 7 "sort": { 8 score: {$meta: "searchScore"}, // optional field 9 "<field-to-sort>": <sort-order>, // 1 or -1, or a document 10 ... 11 } 12 } 13 }
Parameter | 说明 | |||||
---|---|---|---|---|---|---|
| ||||||
| 必需。作为排序依据的字段的名称。 | |||||
| 必需。确定排序顺序。使用 如果要指定 noData字段,请使用具有以下事务语法的文档:
|
示例
以下示例使用 sample_mflix.movies
、sample_airbnb.listingsAndReview
或名为 users
的自定义集合。
索引定义
本页中的示例查询使用 sample_mflix.movies
、 sample_airbnb.listingsAndReview
或自定义集合。如果您在这些集合上创建以下索引,则可以针对索引字段运行示例查询。
movies
集合的索引定义将指定以下内容:
索引
awards.wins
字段为:number
用于排序和查询的类型numberFacet
用于运行分面查询的类型
索引
released
字段为:date
用于排序和查询的类型dateFacet
用于运行分面查询的类型
索引
title
字段为:token
排序类型string
用于查询的类型
1 { 2 "mappings": { 3 "dynamic": true, 4 "fields": { 5 "awards": { 6 "dynamic": false, 7 "fields": { 8 "wins": [ 9 { 10 "type": "number" 11 }, 12 { 13 "type": "numberFacet" 14 } 15 ] 16 }, 17 "type": "document" 18 }, 19 "released": [ 20 { 21 "type": "date" 22 }, 23 { 24 "type": "dateFacet" 25 } 26 ], 27 "title": [{ 28 "type": "token" 29 }, { 30 "type": "string" 31 }] 32 } 33 } 34 }
对于前面的索引定义,Atlas Search 创建一个名为 default
的索引,并在指定字段上使用静态映射。
针对 sample_airbnb.listingsAndReviews
集合的示例查询使用了以下索引。索引定义指定了集合中字段的动态映射:
{ "mappings": { "dynamic": true } }
users
集合包含以下文档:
db.users.insertMany([ { "_id": 0, "a": UUID("1a324de2-e34b-c87e-f2a1-42ce37ad74ed"), "b": "hello", "c": ObjectId("507f1f77bcf86cd799439011") }, { "_id": 1, "a": UUID("3b241101-e2bb-4255-8caf-4136c566a962"), "b": "hello", "c": true }, { "_id": 2, "a": UUID("dee11d4e-63c6-4d90-983c-5c9f1e79e96c"), "b": "hello", "c": "foo" }, { "_id": 3, "b": "hello", "c": UUID("3be11d4e-62cb-4e95-9a3c-5c9f1e56c732") }, { "_id": 4, "a": UUID("d3c12e1c-c36e-25ed-7c3e-1e7f1e53c752"), "b": "hello", "c": null }, { "_id": 5, "a": UUID("d73f181e-cdda-42b4-b844-4d6e172e9bc8"), "b": "hello", "c": [] } { "_id": 6, "a": UUID("7eeddf21-b313-4a5c-81c2-c68915daa618"), "b": "hello", } ])
users
集合的索引定义将指定以下内容:
动态索引除名为
c
的字段之外的所有字段。将名为
c
的字段静态索引为以下类型以进行排序:token
uuid
objectId
boolean
1 { 2 "mappings": { 3 "dynamic": true, 4 "fields": { 5 "c": [ 6 { "type": "token" }, 7 { "type": "uuid" }, 8 { "type": "objectId" }, 9 { "type": "boolean" }, 10 { "type": "number" } 11 ] 12 } 13 } 14 }
对于前面的集合,Atlas Search 会创建一个名为 default
的索引,并在指定字段上使用指定的映射。
日期搜索和排序
对 sample_mflix.movies
命名空间的以下查询使用 $search
阶段执行以下操作:
使用范围操作符搜索 2010 年 1 月 1 日至 2015 年 1 月 1 日之间发布的电影。
使用
sort
选项按发布日期降序排列结果。
该查询使用$limit
阶段将输出限制为5
文档。 它还使用$project
阶段省略结果中除title
和released
之外的所有字段。
db.movies.aggregate([ { "$search": { "range": { "path": "released", "gt": ISODate("2010-01-01T00:00:00.000Z"), "lt": ISODate("2015-01-01T00:00:00.000Z") }, "sort": { "released": -1 } } }, { "$limit": 5 }, { "$project": { "_id": 0, "title": 1, "released": 1 } } ])
[ { title: 'Cold in July', released: ISODate("2014-12-31T00:00:00.000Z") }, { title: 'The Gambler', released: ISODate("2014-12-31T00:00:00.000Z") }, { title: 'Force Majeure', released: ISODate("2014-12-30T00:00:00.000Z") }, { title: 'LFO', released: ISODate("2014-12-27T00:00:00.000Z") }, { title: 'Peace After Marriage', released: ISODate('2014-12-26T00:00:00.000Z') } ]
数字搜索和排序
对 sample_mflix.movies
命名空间的以下查询使用 $search
阶段执行以下操作:
搜索获奖电影。
使用
sort
选项按降序排列结果。
该查询使用$limit
阶段将输出限制为5
文档。 它还使用$project
阶段省略结果中除title
和awards.wins
之外的所有字段。
db.movies.aggregate([ { "$search": { "range": { "path": "awards.wins", "gt": 3 }, "sort": { "awards.wins": -1 } } }, { "$limit": 5 }, { "$project": { "_id": 0, "title": 1, "awards.wins": 1 } } ])
[ { title: '12 Years a Slave', awards: { wins: 267 } }, { title: 'Gravity', awards: { wins: 231 } }, { title: 'Gravity', awards: { wins: 231 } }, { title: 'Birdman: Or (The Unexpected Virtue of Ignorance)', awards: { wins: 210 } }, { title: 'Boyhood', awards: { wins: 185 } }, ]
字符串搜索和排序
对 sample_mflix.movies
命名空间的以下查询使用 $search
阶段执行以下操作:
搜索标题中包含“
country
”一词的电影。使用
sort
选项以升序排列结果。
该查询使用$limit
阶段将输出限制为5
文档。 它还使用$project
阶段执行以下操作:
忽略结果中除
title
之外的所有字段。添加名为
score
的字段。
db.movies.aggregate([ { "$search": { "text": { "path": "title", "query": "country" }, "sort": { "title": 1 } } }, { "$limit": 5 }, { "$project": { "_id": 0, "title": 1, "score": { "$meta": "searchScore" } } } ])
[ { title: 'A Country Called Home', score: 2.536633253097534 }, { title: 'A Month in the Country', score: 2.258953094482422 }, { title: 'A Quiet Place in the Country', score: 2.0360684394836426 }, { title: 'A Sunday in the Country', score: 2.258953094482422 }, { title: 'Another Country', score: 3.3635599613189697 } ]
按 ObjectId 排序
以下查询使用范围操作符在 sample_mflix.movies
集合中的 released
字段中搜索在 2015-01-01
和 2015-12-31
之间上映的电影。它按 _id
字段对结果进行排序,该字段包含 ObjectId
类型的值,按降序排列。
db.movies.aggregate([ { "$search": { "range": { "path": "released", "gt": ISODate("2015-01-01T00:00:00.000Z"), "lt": ISODate("2015-12-31T00:00:00.000Z") }, "sort": { "_id": -1 } } }, { "$limit": 5 }, { "$project": { "_id": 1, "title": 1, "released": 1, "score": { "$meta": "searchScore" } } } ])
[ { _id: ObjectId('573a13fbf29313caabdedf31'), title: 'No Home Movie', released: ISODate('2015-08-10T00:00:00.000Z'), score: 1 }, { _id: ObjectId('573a13fbf29313caabdedf30'), title: 'Our Loved Ones', released: ISODate('2015-08-12T00:00:00.000Z'), score: 1 }, { _id: ObjectId('573a13faf29313caabded406'), title: 'The Red Spider', released: ISODate('2015-11-20T00:00:00.000Z'), score: 1 }, { _id: ObjectId('573a13faf29313caabded1d6'), title: 'The Laundryman', released: ISODate('2015-07-11T00:00:00.000Z'), score: 1 }, { _id: ObjectId('573a13faf29313caabdecaf3'), title: 'Right Now, Wrong Then', released: ISODate('2015-09-01T00:00:00.000Z'), score: 1 } ]
按 UUID 排序
以下查询在 users
集合的字段 b
中搜索术语 hello
。该查询按包含多态数据(以演示排序顺序)的字段 a
对结果进行升序排序。
db.users.aggregate([ { "$search": { "text": { "path": "b", "query": "hello" }, "sort": { "a": 1 } } }, { "$project": { "_id": 1, "a": 1, "score": { "$meta": "searchScore" } } } ])
[ { _id: 3, score: 0.029335692524909973 }, { _id: 0, a: UUID('1a324de2-e34b-c87e-f2a1-42ce37ad74ed'), score: 0.029335692524909973 }, { _id: 1, a: UUID('3b241101-e2bb-4255-8caf-4136c566a962'), score: 0.029335692524909973 }, { _id: 6, a: UUID('7eeddf21-b313-4a5c-81c2-c68915daa618'), score: 0.029335692524909973 }, { _id: 4, a: UUID('d3c12e1c-c36e-25ed-7c3e-1e7f1e53c752'), score: 0.029335692524909973 }, { _id: 5, a: UUID('d73f181e-cdda-42b4-b844-4d6e172e9bc8'), score: 0.029335692524909973 }, { _id: 2, a: UUID('dee11d4e-63c6-4d90-983c-5c9f1e79e96c'), score: 0.029335692524909973 } ]
按空值排序
考虑以下查询,使用文本操作符在b
hello
users
字段中搜索 集合中的字符串 。然后,该查询按字段c
对结果进行排序,该字段包含集合中某些文档的 null 值或缺失值。
在升序排序过程中, Atlas Search默认会在结果顶部返回包含 null 或缺失值的文档,如以下示例所示:
db.users.aggregate([ { "$search": { "text": { "path": "b", "query": "hello" }, "sort": { "c": 1 } } }, { "$project": { "_id": 1, "c": 1, "score": { "$meta": "searchScore" } } } ])
[ { _id: 4, c: null, score: 0.029335692524909973 }, { _id: 5, c: [], score: 0.029335692524909973 }, { _id: 6, score: 0.029335692524909973 }, { _id: 2, c: 'foo', score: 0.029335692524909973 }, { _id: 3, c: UUID('3be11d4e-62cb-4e95-9a3c-5c9f1e56c732'), score: 0.029335692524909973 }, { _id: 0, c: ObjectId('507f1f77bcf86cd799439011'), score: 0.029335692524909973 }, { _id: 1, c: true, score: 0.029335692524909973 } ]
在降序排序期间, Atlas Search默认在结果底部返回包含 null 或缺失值的文档,如以下示例所示:
db.users.aggregate([ { "$search": { "text": { "path": "b", "query": "hello" }, "sort": { "c": -1 } } }, { "$project": { "_id": 1, "c": 1, "score": { "$meta": "searchScore" } } } ])
[ { _id: 1, c: true, score: 0.025981096550822258 }, { _id: 0, c: ObjectId('507f1f77bcf86cd799439011'), score: 0.025981096550822258 }, { _id: 3, c: UUID('3be11d4e-62cb-4e95-9a3c-5c9f1e56c732'), score: 0.025981096550822258 }, { _id: 2, c: 'foo', score: 0.025981096550822258 }, { _id: 4, c: null, score: 0.025981096550822258 }, { _id: 5, c: [], score: 0.025981096550822258 }, { _id: 6, score: 0.025981096550822258 } ]
注意
设置 noData: lowest
与默认相同。
如果您在升序排序期间将 noData
字段指定为 lowest
,则Atlas Search会在结果顶部返回包含 null 值或缺失值的文档,如以下示例所示。
db.users.aggregate([ { "$search": { "text": { "path": "b", "query": "hello" }, "sort": { "c": { "order": 1, "noData": "lowest" } } } }, { "$project": { "_id": 1, "c": 1, "score": { "$meta": "searchScore" } } } ])
[ { _id: 4, c: null, score: 0.029335692524909973 }, { _id: 5, c: [], score: 0.029335692524909973 }, { _id: 6, score: 0.029335692524909973 }, { _id: 2, c: 'foo', score: 0.029335692524909973 }, { _id: 3, c: UUID('3be11d4e-62cb-4e95-9a3c-5c9f1e56c732'), score: 0.029335692524909973 }, { _id: 0, c: ObjectId('507f1f77bcf86cd799439011'), score: 0.029335692524909973 }, { _id: 1, c: true, score: 0.029335692524909973 } ]
如果您在降序排序期间将 noData
字段指定为 lowest
,则Atlas Search在结果底部返回包含 null 值或缺失值的文档,如以下示例所示。
db.users.aggregate([ { "$search": { "text": { "path": "b", "query": "hello" }, "sort": { "c": { "order": -1, "noData": "lowest" } } } }, { "$project": { "_id": 1, "c": 1, "score": { "$meta": "searchScore" } } } ])
[ { _id: 1, c: true, score: 0.025981096550822258 }, { _id: 0, c: ObjectId('507f1f77bcf86cd799439011'), score: 0.025981096550822258 }, { _id: 3, c: UUID('3be11d4e-62cb-4e95-9a3c-5c9f1e56c732'), score: 0.025981096550822258 }, { _id: 2, c: 'foo', score: 0.025981096550822258 }, { _id: 4, c: null, score: 0.025981096550822258 }, { _id: 5, c: [], score: 0.025981096550822258 }, { _id: 6, score: 0.025981096550822258 } ]
如果您在升序排序期间将 noData
字段指定为 highest
,则Atlas Search将在结果底部返回包含 null 值或缺失值的文档,如以下示例所示。
db.users.aggregate([ { "$search": { "text": { "path": "b", "query": "hello" }, "sort": { "c": { "order": 1, "noData": "highest" } } } }, { "$project": { "_id": 1, "c": 1, "score": { "$meta": "searchScore" } } } ])
[ { _id: 2, c: 'foo', score: 0.025981096550822258 }, { _id: 3, c: UUID('3be11d4e-62cb-4e95-9a3c-5c9f1e56c732'), score: 0.025981096550822258 }, { _id: 0, c: ObjectId('507f1f77bcf86cd799439011'), score: 0.025981096550822258 }, { _id: 1, c: true, score: 0.025981096550822258 }, { _id: 4, c: null, score: 0.025981096550822258 }, { _id: 5, c: [], score: 0.025981096550822258 }, { _id: 6, score: 0.025981096550822258 } ]
如果您在降序排序期间将 noData
字段指定为 highest
,则Atlas Search在结果顶部返回包含 null 值或缺失值的文档,如以下示例所示。
db.users.aggregate([ { "$search": { "text": { "path": "b", "query": "hello" }, "sort": { "c": { "order": -1, "noData": "highest" } } } }, { "$project": { "_id": 1, "c": 1, "score": { "$meta": "searchScore" } } } ])
[ { _id: 4, c: null, score: 0.025981096550822258 }, { _id: 5, c: [], score: 0.025981096550822258 }, { _id: 6, score: 0.025981096550822258 }, { _id: 1, c: true, score: 0.025981096550822258 }, { _id: 0, c: ObjectId('507f1f77bcf86cd799439011'), score: 0.025981096550822258 }, { _id: 3, c: UUID('3be11d4e-62cb-4e95-9a3c-5c9f1e56c732'), score: 0.025981096550822258 }, { _id: 2, c: 'foo', score: 0.025981096550822258 } ]
具有 "_id": 4
、 "_id": 5
和 "_id": 6
的文档的顺序是随机的,因为Atlas Search在排序时将空值和缺失值视为相等。
对多类型数组进行排序
考虑对 users集合进行以下查询,给定另文档,其字段 c
具有多类型大量:
db.users.insertOne({ "_id": 7, "a": UUID("03e32aa9-1cbd-43b8-b9d6-18b171a03cc7"), "b": "hello", "c": [ false, null, 15 ] })
以下使用文本操作符在搜索字段b
中查询字符串hello
,并按字段c
对结果进行排序。
对于升序排序, Atlas Search使用具有最低BSON类型的元素来表示多类型大量。默认, Atlas Search将空值或缺失值视为最低BSON值。因此, Atlas Search使用null
来表示具有_id: 7
的文档的多类型大量,并在结果顶部返回此文档以及其他空值和缺失值。
要学习;了解更多信息,请参阅按空值和缺失值排序以及使用多种类型对数组进行排序。
db.users.aggregate([ { "$search": { "text": { "path": "b", "query": "hello" }, "sort": { "c": 1 } } }, { "$project": { "_id": 1, "c": 1, "score": { "$meta": "searchScore" } } } ])
[ { _id: 4, c: null, score: 0.025981096550822258 }, { _id: 5, c: [], score: 0.025981096550822258 }, { _id: 6, score: 0.025981096550822258 } { _id: 7, c: [ false, null, 15 ], score: 0.025981096550822258 }, { _id: 2, c: 'foo', score: 0.025981096550822258 }, { _id: 3, c: UUID('3be11d4e-62cb-4e95-9a3c-5c9f1e56c732'), score: 0.025981096550822258 }, { _id: 0, c: ObjectId('507f1f77bcf86cd799439011'), score: 0.025981096550822258 }, { _id: 1, c: true, score: 0.025981096550822258 } ]
具有 "_id": 4
、 "_id": 5
、 "_id": 6
和 "_id": 7
的文档的顺序是随机的,因为Atlas Search在排序时将 null 值和缺失值视为相等。
对于降序排序, Atlas Search使用具有最高BSON类型的元素来表示多类型大量。 Atlas Search使用false
来表示具有_id: 7
的文档的多类型大量,因为这是大量中最高的BSON类型。由于Atlas Search还将true
false
值排名在 值之上,因此Atlas Search在包含_id: 1
的文档之后返回此文档。
要学习;了解更多信息,请参阅按空值和缺失值排序以及使用多种类型对数组进行排序。
db.users.aggregate([ { "$search": { "text": { "path": "b", "query": "hello" }, "sort": { "c": -1 } } }, { "$project": { "_id": 1, "c": 1, "score": { "$meta": "searchScore" } } } ])
[ { _id: 1, c: true, score: 0.025981096550822258 }, { _id: 7, c: [ false, null, 15 ], score: 0.025981096550822258 }, { _id: 0, c: ObjectId('507f1f77bcf86cd799439011'), score: 0.025981096550822258 }, { _id: 3, c: UUID('3be11d4e-62cb-4e95-9a3c-5c9f1e56c732'), score: 0.025981096550822258 }, { _id: 2, c: 'foo', score: 0.025981096550822258 } { _id: 4, c: null, score: 0.025981096550822258 }, { _id: 5, c: [], score: 0.025981096550822258 }, { _id: 6, score: 0.025981096550822258 }, ]
具有 "_id": 4
、 "_id": 5
和 "_id": 6
的文档的顺序是随机的,因为Atlas Search在排序时将空值和缺失值视为相等。
以下查询指定noData: highest
以在排序期间设立null 值设置为最高BSON类型。
对于升序排序, Atlas Search使用具有最低BSON类型的元素来表示多类型大量。查询指定 noData: highest
将空值或缺失值视为最高BSON值,因此Atlas Search使用15
表示具有_id: 7
的文档的多类型大量,因为数字是大量中下一个最低的BSON类型。
要学习;了解更多信息,请参阅按空值和缺失值排序以及使用多种类型对数组进行排序。
db.users.aggregate([ { "$search": { "text": { "path": "b", "query": "hello" }, "sort": { "c": { "order": 1, "noData": "highest" } } } }, { "$project": { "_id": 1, "c": 1, "score": { "$meta": "searchScore" } } } ])
[ { _id: 7, c: [ false, null, 15 ], score: 0.025981096550822258 }, { _id: 2, c: 'foo', score: 0.025981096550822258 }, { _id: 3, c: UUID('3be11d4e-62cb-4e95-9a3c-5c9f1e56c732'), score: 0.025981096550822258 }, { _id: 0, c: ObjectId('507f1f77bcf86cd799439011'), score: 0.025981096550822258 }, { _id: 1, c: true, score: 0.025981096550822258 }, { _id: 4, c: null, score: 0.025981096550822258 }, { _id: 5, c: [], score: 0.025981096550822258 }, { _id: 6, score: 0.025981096550822258 } ]
具有 "_id": 4
、 "_id": 5
和 "_id": 6
的文档的顺序是随机的,因为Atlas Search在排序时将空值和缺失值视为相等。
对于降序排序, Atlas Search使用具有最高BSON类型的元素来表示多类型大量。由于查询将 noData
highest
null
_id: 7
字段指定为 ,以设立空值或缺失值设置为最高BSON值,因此Atlas Search使用 表示具有 的文档的多类型大量,并在以下位置返回此文档:结果的顶部以及其他空值和缺失值。
要学习;了解更多信息,请参阅按空值和缺失值排序以及使用多种类型对数组进行排序。
db.users.aggregate([ { "$search": { "text": { "path": "b", "query": "hello" }, "sort": { "c": { "order": -1, "noData": "highest" } } } }, { "$project": { "_id": 1, "c": 1, "score": { "$meta": "searchScore" } } } ])
[ { _id: 4, c: null, score: 0.025981096550822258 }, { _id: 5, c: [], score: 0.025981096550822258 }, { _id: 6, score: 0.025981096550822258 }, { _id: 7, c: [ false, null, 15 ], score: 0.025981096550822258 }, { _id: 1, c: true, score: 0.025981096550822258 }, { _id: 0, c: ObjectId('507f1f77bcf86cd799439011'), score: 0.025981096550822258 }, { _id: 3, c: UUID('3be11d4e-62cb-4e95-9a3c-5c9f1e56c732'), score: 0.025981096550822258 }, { _id: 2, c: 'foo', score: 0.025981096550822258 } ]
具有 "_id": 4
、 "_id": 5
、 "_id": 6
和 "_id": 7
的文档的顺序是随机的,因为Atlas Search在排序时将 null 值和缺失值视为相等。
按布尔值排序
以下查询在 sample_airbnb.listingsAndReviews
集合中搜索 Portugal
中的属性,并按 boolean
字段 is_location_exact
对结果进行降序排序。
该查询使用 $limit
阶段将输出限制为 5
个文档。它还使用 $project
阶段省略结果中除 name
、property_type
、address.country
和 address.location.is_location_exact
之外的所有字段。
1 db.listingsAndReviews.aggregate([ 2 { 3 "$search": { 4 "text": { 5 "path": "address.country", 6 "query": "Portugal" 7 }, 8 "sort": { 9 "address.location.is_location_exact": -1, 10 } 11 } 12 }, 13 { 14 "$limit": 5 15 }, 16 { 17 "$project": { 18 "_id": 0, 19 "name": 1, 20 "property_type": 1, 21 "address.country": 1, 22 "address.location.is_location_exact": 1 23 } 24 } 25 ])
1 [ 2 { 3 name: 'BBC OPORTO 4X2', 4 property_type: 'Apartment', 5 address: { country: 'Portugal', location: { is_location_exact: true } } 6 }, 7 { 8 name: 'Heroísmo IV', 9 property_type: 'Apartment', 10 address: { country: 'Portugal', location: { is_location_exact: true } } 11 }, 12 { 13 name: 'Spacious and well located apartment', 14 property_type: 'Apartment', 15 address: { country: 'Portugal', location: { is_location_exact: true } } 16 }, 17 { 18 name: 'Renovated Classic Design Studio with Sun Room', 19 property_type: 'Apartment', 20 address: { country: 'Portugal', location: { is_location_exact: true } } 21 }, 22 { 23 name: "O'Porto Studio | Historic Center", 24 property_type: 'Loft', 25 address: { country: 'Portugal', location: { is_location_exact: true } } 26 } 27 ]
在前面的结果中,文档的 is_location_exact
值为 true
,因为在降序排序中,Atlas Search 将 true
值排列在 false
值之上。如果通过将前面查询的第 9 行的值更改为 1
来执行升序排序,则 Atlas Search 会对 false
值高于 true
值的文档进行排名,并返回以下文档:
[ { name: 'Ribeira Charming Duplex', property_type: 'House', address: { country: 'Portugal', location: { is_location_exact: false } } }, { name: 'Be Happy in Porto', property_type: 'Loft', address: { country: 'Portugal', location: { is_location_exact: false } } }, { name: 'Downtown Oporto Inn (room cleaning)', property_type: 'Hostel', address: { country: 'Portugal', location: { is_location_exact: false } } }, { name: 'A Casa Alegre é um apartamento T1.', property_type: 'Apartment', address: { country: 'Portugal', location: { is_location_exact: false } } }, { name: 'FloresRooms 3T', property_type: 'Apartment', address: { country: 'Portugal', location: { is_location_exact: false } } } ]
复合搜索和排序
以下查询使用 $search
阶段执行以下操作:
搜索标题中含有
dance
字样的电影,优先搜索获得 2 个或更多奖项且在 1990 年 1 月 1 日之后上映的电影。按奖项数量降序对结果进行排序,然后按电影标题升序进行排序,然后按发行日期降序进行排序。
该查询使用$limit
阶段将输出限制为10
文档。 它还使用$project
阶段执行以下操作:
忽略结果中除
title
、released
和awards.wins
之外的所有字段。添加名为
score
的字段。
db.movies.aggregate([ { "$search": { "compound": { "must": [{ "text": { "path": "title", "query": "dance" } }], "should": [{ "range": { "path": "awards.wins", "gte": 2 } }, { "range": { "path": "released", "gte": ISODate("1990-01-01T00:00:00.000Z") } }] }, "sort": { "awards.wins": -1, "title": 1, "released": -1 } } }, { "$limit": 10 }, { "$project": { "_id": 0, "title": 1, "released": 1, "awards.wins": 1, "score": { "$meta": "searchScore" } } } ])
[ { title: 'Shall We Dance?', released: ISODate("1997-07-11T00:00:00.000Z"), awards: { wins: 57 }, score: 4.9811458587646484 }, { title: 'Shall We Dance?', released: ISODate("1997-07-11T00:00:00.000Z"), awards: { wins: 57 }, score: 4.9811458587646484 }, { title: 'War Dance', released: ISODate("2008-11-01T00:00:00.000Z"), awards: { wins: 11 }, score: 5.466421127319336 }, { title: 'Dance with the Devil', released: ISODate("1997-10-31T00:00:00.000Z"), awards: { wins: 6 }, score: 4.615056037902832 }, { title: 'Save the Last Dance', released: ISODate("2001-01-12T00:00:00.000Z"), awards: { wins: 6 }, score: 4.615056037902832 }, { title: 'Dance with a Stranger', released: ISODate("1985-08-09T00:00:00.000Z"), awards: { wins: 4 }, score: 3.615056037902832 }, { title: 'The Baby Dance', released: ISODate("1998-08-23T00:00:00.000Z"), awards: { wins: 4 }, score: 4.981145858764648 }, { title: 'Three-Step Dance', released: ISODate("2004-02-19T00:00:00.000Z"), awards: { wins: 4 }, score: 4.981145858764648 }, { title: "Cats Don't Dance", released: ISODate("1997-03-26T00:00:00.000Z"), awards: { wins: 3 }, score: 4.981145858764648 }, { title: 'Dance Me Outside', released: ISODate("1995-03-10T00:00:00.000Z"), awards: { wins: 3 }, score: 4.981145858764648 } ]
分面搜索和排序
以下查询使用 $search
阶段执行以下操作:
使用范围操作符搜索 2010 年 1 月 1 日至 2015 年 1 月 1 日之间发布的电影。
统计荣获
1
、5
、10
和15
奖项的电影数量。获取
2010-01-01
、2011-01-01
、2012-01-01
、2013-01-01
、2014-01-01
和2015-01-01
发行的电影数量的计数。使用
sort
选项按发布日期降序排列结果。
该查询使用$limit
阶段执行以下操作:
在
docs
输出字段中将输出限制为5
个文档。在
meta
输出字段中将输出限制为1
个文档。
它使用$project
阶段省略除awards.wins
、 released
和title
字段之外的所有字段。
它还使用$replaceWith
阶段将存储在$$SEARCH_META
变量中的元数据结果包含在meta
输出字段中,并使用$set
阶段将meta
字段添加到结果中。
db.movies.aggregate([ { "$search": { "facet": { "operator": { "range": { "path": "released", "gt": ISODate("2010-01-01T00:00:00.000Z"), "lt": ISODate("2015-01-01T00:00:00.000Z") } }, "facets": { "awardsFacet": { "type": "number", "path": "awards.wins", "boundaries" : [1,5,10,15] }, "releasedFacet" : { "type" : "date", "path" : "released", "boundaries" : [ISODate("2010-01-01T00:00:00.000Z"), ISODate("2011-01-01T00:00:00.000Z"), ISODate("2012-01-01T00:00:00.000Z"), ISODate("2013-01-01T00:00:00.000Z"), ISODate("2014-01-01T00:00:00.000Z"), ISODate("2015-01-01T00:00:00.000Z")] } } }, "sort": { "released": -1 } } }, { "$facet": { "docs": [ { "$limit": 5 }, { "$project": { "_id": 0, "title": 1, "released": 1, "awards.wins": 1 } } ], "meta": [ {"$replaceWith": "$$SEARCH_META"}, {"$limit": 1} ] } }, { "$set": { "meta": { "$arrayElemAt": ["$meta", 0] } } } ])
[ { docs: [ { title: 'Cold in July', released: ISODate("2014-12-31T00:00:00.000Z"), awards: { wins: 1 } }, { title: 'The Gambler', released: ISODate("2014-12-31T00:00:00.000Z"), awards: { wins: 7 } }, { title: 'Force Majeure', released: ISODate("2014-12-30T00:00:00.000Z"), awards: { wins: 31 } }, { title: 'LFO', released: ISODate("2014-12-27T00:00:00.000Z"), awards: { wins: 3 } }, { title: 'Peace After Marriage', released: ISODate('2014-12-26T00:00:00.000Z'), awards: { wins: 5 } } ], meta: { count: { lowerBound: Long("4821") }, facet: { releasedFacet: { buckets: [ { _id: ISODate("2010-01-01T00:00:00.000Z"), count: Long("857") }, { _id: ISODate("2011-01-01T00:00:00.000Z"), count: Long("909") }, { _id: ISODate("2012-01-01T00:00:00.000Z"), count: Long("903") }, { _id: ISODate("2013-01-01T00:00:00.000Z"), count: Long("1063") }, { _id: ISODate("2014-01-01T00:00:00.000Z"), count: Long("1089") } ] }, awardsFacet: { buckets: [ { _id: 1, count: Long("2330") }, { _id: 5, count: Long("604") }, { _id: 10, count: Long("233") } ] } } } } } ]
按分数排序
以下示例演示如何按结果中文档的分数对结果进行排序。这些示例演示了如何执行以下操作:
首先按升序对结果进行排序,以检索分数最低的文档。
按分数对结果进行降序排序,对分数相同的结果任意排序。
按分数对结果进行排序,对于具有相同分数的结果,使用唯一字段进行排序。
以下查询使用 $search
阶段执行以下操作:
搜索标题中包含“
story
”一词的电影。按分数升序对结果进行排序。
该查询使用$limit
阶段将输出限制为5
文档。 它还使用$project
阶段执行以下操作:
忽略结果中除
title
之外的所有字段。添加名为
score
的字段。
db.movies.aggregate([ { "$search": { "text": { "path": "title", "query": "story" }, "sort": {score: {$meta: "searchScore", order: 1}} } }, { "$limit": 5 }, { "$project": { "_id": 0, "title": 1, "score": {$meta: "searchScore"} } } ])
[ { title: 'Do You Believe in Miracles? The Story of the 1980 U.S. Hockey Team', score: 0.8674521446228027 }, { title: 'Once in a Lifetime: The Extraordinary Story of the New York Cosmos', score: 0.9212141036987305 }, { title: 'The Source: The Story of the Beats and the Beat Generation', score: 0.9820802211761475 }, { title: 'If These Knishes Could Talk: The Story of the NY Accent', score: 0.9820802211761475 }, { title: 'Dream Deceivers: The Story Behind James Vance vs. Judas Priest', score: 1.051558256149292 } ]
以下查询使用 $search
阶段执行以下操作:
搜索标题中包含“
summer
”一词的电影。按分数对结果进行降序排序,对分数相同的结果任意排序。
该查询使用$limit
阶段将输出限制为5
文档。 它还使用$project
阶段执行以下操作:
忽略结果中除
_id
和title
之外的所有字段。添加名为
score
的字段。
db.movies.aggregate([ { "$search": { "text": { "path": "title", "query": "summer" }, "sort": {score: {$meta: "searchScore"}} } }, { "$limit": 5 }, { "$project": { "_id": 1, "title": 1, "score": {$meta: "searchScore"} } } ])
[ { _id: ObjectId("573a1398f29313caabcea21e"), title: 'Summer', score: 3.5844719409942627 }, { _id: ObjectId("573a13a6f29313caabd18eca"), title: 'Summer Things', score: 3.000213623046875 }, { _id: ObjectId("573a13b8f29313caabd4c1d0"), title: 'Summer Palace', score: 3.000213623046875 }, { _id: ObjectId("573a1394f29313caabcde8e8"), title: 'Summer Stock', score: 3.000213623046875 }, { _id: ObjectId("573a13acf29313caabd284fa"), title: 'Wolf Summer', score: 3.000213623046875 } ]
以下查询使用 $search
阶段执行以下操作:
搜索标题中包含“
prince
”一词的电影。对于分数相同的结果,首先按分数对结果进行排序,然后按
released
字段的值按升序排序。
该查询使用$limit
阶段将输出限制为5
文档。 它还使用$project
阶段执行以下操作:
忽略结果中除
title
和released
之外的所有字段。添加名为
score
的字段。
db.movies.aggregate([ { "$search": { "text": { "path": "title", "query": "prince" }, "sort": {score: {$meta: "searchScore"}, "released": 1} } }, { "$limit": 5 }, { "$project": { "_id": 0, "title": 1, "released": 1, "score": {$meta: "searchScore"} } } ])
[ { title: 'Prince', released: ISODate("2015-08-14T00:00:00.000Z"), score: 4.168826103210449 }, { title: 'Prince Avalanche', released: ISODate("2013-09-19T00:00:00.000Z"), score: 3.4893198013305664 }, { title: 'The Prince', released: ISODate("2014-08-22T00:00:00.000Z"), score: 3.4893198013305664 }, { title: 'Prince of Foxes', released: ISODate("1949-12-23T00:00:00.000Z"), score: 3.0002830028533936 }, { title: 'The Oil Prince', released: ISODate("1966-01-01T00:00:00.000Z"), score: 3.0002830028533936 } ]