Docs 菜单
Docs 主页
/
MongoDB Atlas
/ / / /

对 Atlas Search 结果进行排序

在此页面上

  • Overview
  • 使用
  • 行为
  • Considerations
  • 限制
  • 兼容性
  • 语法
  • 示例
  • 索引定义
  • 日期搜索和排序
  • 数字搜索和排序
  • 字符串搜索和排序
  • 按 ObjectId 排序
  • 按 UUID 排序
  • 按空值排序
  • 对多类型数组进行排序
  • 按布尔值排序
  • 复合搜索和排序
  • 分面搜索和排序
  • 按分数排序

Atlas Search 允许您在 Atlas Search 索引中定义的字段中,按升序或降序对结果进行排序。您可以使用 sort 选项按以下字段类型进行排序:

  • boolean

  • date

  • number (整数、浮点数和 double 值)

  • objectId

  • uuid

  • string (索引为 词元类型)

您还可以按结果中文档的分数和 空值进行排序。

要对 Atlas Search 结果进行排序,必须执行以下步骤:

  1. 在字段上创建 Atlas Search 索引,以便对结果进行排序。

    要对 booleandatenumberUUIDobjectId 字段排序,请使用动态或静态映射。要对字符串字段排序,您必须使用静态映射将字段索引为 token 类型。

  2. 使用sort选项针对您在索引中定义的字段创建并运行查询以进行排序。 要了解详情,请参阅语法。

sort 选项采用一个文档,该文档指定要作为排序依据的字段以及相应的排序顺序。对于支持的数据类型,Atlas Search 遵循 MongoDB 比较顺序。它像 BinData 一样处理 UUID 值。要了解更多信息,请参阅不存在的字段。

您可以指定以下排序顺序来对结果进行排序:

1

按升序排序。

当您按升序排序时,Atlas Search 将先返回值缺失的文档,然后再返回包含值的文档。

-1

按降序排序。

您还可以按分数升序或降序排序。 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使用null ,因为它是支持的最低BSON类型。

  • 对于降序排序, Atlas Search使用true ,因为它是大量中最高的BSON类型,并且Atlas Search将true 值排在false 值之上。

但是,如果您在noData: highest sort语法中设立 , Atlas Search会将 null 值和缺失值视为最高BSON类型。对于示例大量,以下行为适用:

  • 对于升序排序, Atlas Search使用15 ,因为它现在是大量中最低的BSON类型。

  • 对于降序排序, Atlas Search使用null ,因为它现在是大量中最高的BSON类型。

要学习;了解更多信息,请参阅按空值和缺失值排序。

有关示例,请参阅对多类型数组进行排序。

Atlas Search将 null 值视为等于缺失值和空值,并且在排序时,具有这些值的文档的顺序是不确定的。

默认, Atlas Search遵循MongoDB比较和排序顺序,并将空值视为低于所有其他支持的BSON 类型。因此,升序排序时,空值出现在结果的顶部;降序排序时,空值出现在结果的底部。

要配置 null 值在结果中出现的位置,请在noData sort语法中指定 字段。noData 字段采用以下值:

  • lowest (默认):在排序期间将空值设置为最低的BSON类型。升序排序时,将空值排序在结果的顶部;降序排序时,将空值排序在结果的底部。

  • highest:在排序期间将 null 值设置为最高BSON类型。在升序排序期间,将空值排序在结果的底部;在降序排序时,将空值排序在顶部。

注意

对具有包含 null 值或缺失值的多种类型的数组进行排序时,同样的行为也适用。

有关示例,请参阅按空值排序和对多类型数组排序。

要按嵌入式文档字段对父文档进行排序,必须执行以下操作:

  • 将嵌入式文档子字段的父项索引为文档类型。

  • 将嵌入文档中带有 string 值的子字段索引为标记类型。对于带有数字和日期值的子字段,启用动态映射可自动为这些字段编制索引。

Atlas Search 仅对父文档进行排序。 它不会对文档数组中的子字段进行排序。 有关示例,请参阅排序示例。

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
说明

score

<field-to-sort>

必需。作为排序依据的字段的名称。

<sort-order>

必需。确定排序顺序。使用 1 进行升序排列,使用 -1 进行降序排列。

如果要指定 noData字段,请使用具有以下事务语法的文档:

"<field-to-sort>": {
order: 1 | -1, // required field
noData: "lowest" | "highest" // optional field
},
...

以下示例使用 sample_mflix.moviessample_airbnb.listingsAndReview 或名为 users 的自定义集合。

本页中的示例查询使用 sample_mflix.moviessample_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阶段省略结果中除titlereleased之外的所有字段。

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阶段省略结果中除titleawards.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 }
]

以下查询使用范围操作符在 sample_mflix.movies 集合中的 released 字段中搜索在 2015-01-012015-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
}
]

以下查询在 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 hellousers字段中搜索 集合中的字符串 。然后,该查询按字段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 对结果进行排序。

注意

在排序语法中设置noData: lowest 与默认相同。

对于升序排序, 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类型的元素来表示多类型大量。由于查询将 noDatahighestnull_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 阶段省略结果中除 nameproperty_typeaddress.countryaddress.location.is_location_exact 之外的所有字段。

1db.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阶段执行以下操作:

  • 忽略结果中除 titlereleasedawards.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 日之间发布的电影。

  • 统计荣获 151015 奖项的电影数量。

  • 获取 2010-01-012011-01-012012-01-012013-01-012014-01-012015-01-01 发行的电影数量的计数。

  • 使用sort选项按发布日期降序排列结果。

该查询使用$limit阶段执行以下操作:

  • docs 输出字段中将输出限制为 5 个文档。

  • meta 输出字段中将输出限制为 1 个文档。

它使用$project阶段省略除awards.winsreleasedtitle字段之外的所有字段。

它还使用$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阶段执行以下操作:

  • 忽略结果中除 _idtitle 之外的所有字段。

  • 添加名为 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阶段执行以下操作:

  • 忽略结果中除 titlereleased 之外的所有字段。

  • 添加名为 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
}
]

后退

5. 定义其他搜索选项