对结果进行分页
在此页面上
在运行 MongoDB 6.0.13 + 或7.0.5 + 的Atlas 集群上,使用 Atlas Search 在参考点之后或之前按顺序检索 $search
查询结果。您可以使用 $search
searchAfter
或 searchBefore
选项按顺序遍历结果,并在应用程序中构建“下一页”和“上一页”功能。
使用
要检索分页结果,请执行以下步骤:
在要查询的字段上创建索引。
在随后的
$search
查询中使用参考点来检索结果中的下一组或上一组文档。要了解有关检索结果以构建“下一页”函数的更多信息,请参阅特定参考点后的Atlas Search 。
要了解有关检索结果以构建“上一页”函数的更多信息,请参阅特定参考点之前的Atlas Search 。
要跳转到结果中的某个页面,请将
$skip
和$limit
与$search
searchAfter
或searchBefore
选项相结合。例如,要从第 3 页跳转到第 5 页的结果,每页 10 个结果,请执行以下操作:使用
searchAfter
和第3页上最后一个结果的引用点(结果30 )来检索结果。返回第 5 页的结果(结果 41-50)。
此处,使用
$skip
和searchAfter
选项可优化查询,只跳过 1 页结果(10 个文档)。相比之下,如果使用$skip
而不使用$search
searchAfter
选项,查询将跳过 4 页结果( 40 个文档)。要了解更多信息,请参阅使用searchAfter
和$skip
从第 2 页跳转到第 5 页。
Considerations
当您对多个文档具有相同值的字段进行排序时,会出现并列。 MongoDB不保证绑定查询结果的排序,这可能会导致在您使用 searchAfter
和 searchBefore
时出现重复和不一致。应用以下原则确保确定性的搜索行为:
按唯一字段对查询进行排序,防止相关性得分并列。
如果要主要按非唯一字段进行排序,请在唯一字段上添加从节点(secondary node from replica set)排序子句以提供服务决胜局。
按不可变字段对查询结果进行排序。 Atlas Search反映您在初始查询和后续查询之间对集合所做的更新。如果您按可变字段(例如
updated_time
)排序,并在第一次和第二次查询之间更新集合,则Atlas Search可能会对相同的文档进行不同的排序。
要了解如何按不可变或唯一字段对查询结果进行排序,请参阅对 Atlas Search 结果进行排序。
检索参考点
要检索某个点的查询结果,必须在 $search
查询中提供参考点。您可以在 $search
阶段之后的 $project
阶段中使用 $meta
关键字 searchSequenceToken
来检索参考点。
语法
1 [{ 2 "$search": { 3 "index": "<index-name>", 4 "<operator-name>"|"<collector-name>": { 5 <operator-specification>|<collector-specification> 6 } 7 "sort": { 8 "score": { 9 "$meta": "searchScore", _id:1 10 } 11 } 12 ... 13 }, 14 { 15 "$project": { 16 { "paginationToken" : { "$meta" : "searchSequenceToken" } } 17 }, 18 ... 19 }]
输出
searchSequenceToken
为结果中的每个文档生成一个基本64编码的词元。 令牌的长度随着查询的排序选项中指定的字段数量的增加而增加。 令牌不与数据库快照绑定。
除非在查询中指定 sort
选项,否则结果中的文档将按默认顺序排序。要了解如何对结果进行排序,请参阅对 Atlas Search 结果进行排序。
特定参考点后的Atlas Search
要在参考点之后搜索,您必须在 $search
查询中通过使用 searchAfter
选项和由 searchSequenceToken
生成的词元来指定参考点。仅当您重新运行由 searchSequenceToken
生成词元的 $search
查询时,才可以使用由 searchSequenceToken
生成的词元。使用词元的后续 $search
查询的语义(搜索字段和值)必须与 searchSequenceToken
生成词元的查询相同。
您可以使用searchAfter
选项在应用程序中构建“下一页”函数。 有关此操作的演示,请参阅本页上的示例。
searchAfter
语法
1 { 2 "$search": { 3 "index": "<index-name>", 4 "<operator-name>"|"<collector-name>": { 5 <operator-specification>|<collector-specification> 6 }, 7 "searchAfter": "<base64-encoded-token>", 8 "sort": { 9 "score": { 10 "$meta": "searchScore", _id:1 11 } 12 } 13 ... 14 }, 15 "$project": { 16 { "paginationToken" : { "$meta" : "searchSequenceToken" } } 17 }, 18 ... 19 }
输出
Atlas Search 返回结果中指定词元之后的文档。 Atlas SearchsearchSequenceToken
$project
$search
11在结果中返回为文档生成的词元,因为您在 阶段之后的 阶段中指定了 (如第 行所示)。这些词元可用作具有相同语义的另一个查询的参考点。
除非在查询中指定 sort
选项,否则结果中的文档将按默认顺序排序。要了解如何对结果进行排序,请参阅对 Atlas Search 结果进行排序。
特定参考点之前的Atlas Search
要在参考点之前Atlas Search ,您必须使用 searchBefore
选项和 searchSequenceToken
生成的词元在$search
查询中指定参考点。 仅当您重新运行 searchSequenceToken
为其生成令牌的$search
查询时,才能使用searchSequenceToken
生成的令牌。 使用该令牌的后续$search
查询的语义(Atlas Search 字段和值)必须与searchSequenceToken
为其生成令牌的查询相同。
您可以使用searchBefore
选项在应用程序中构建“上一页”函数。 要构建“上一页”函数,请结合使用以下内容:
有关此操作的演示,请参阅本页上的searchBefore
查询示例。
searchBefore
语法
1 { 2 "$search": { 3 "index": "<index-name>", 4 "<operator-name>"|"<collector-name>": { 5 <operator-specification>|<collector-specification> 6 }, 7 "searchBefore": "<base64-encoded-token>", 8 "sort": { 9 "score": { 10 "$meta": "searchScore", _id:1 11 } 12 } 13 ... 14 }, 15 "$project": { 16 { "paginationToken" : { "$meta" : "searchSequenceToken" } } 17 }, 18 ... 19 }
searchBefore
输出
Atlas Search 以相反的顺序返回结果中指定标记之前的文档。Atlas Search 还会返回结果中文档的生成标记,因为您在 $search
阶段之后的 $project
阶段中指定了 searchSequenceToken
(如 11 行所示)。这些标记可以用作具有相同语义的另一个查询的参考点。
示例
以下示例使用 sample-mflix.movies 集合,该集合具有名为 default
的带有动态映射的 Atlas Search 索引。如果加载集合并创建索引,则可以对该集合运行以下查询。
searchSequenceToken
查询
以下查询使用以下管道阶段:
$search
以执行以下操作:Atlas Search在集合的
title
字段中搜索术语war
。首先按分数对结果进行排序,然后按
released
字段的值对分数相同的文档进行升序排序。
$limit
阶段将结果限制为10
文档。$project
阶段来执行以下操作:仅包含
title
和released
字段。添加以下字段:
名为
paginationToken
的字段,其中包含每个文档的 Base64 编码词元。名为
score
的字段,包含每个文档的相关性分数。
1 db.movies.aggregate([ 2 { 3 "$search": { 4 "text": { 5 "path": "title", 6 "query": "war" 7 }, 8 "sort": {score: {$meta: "searchScore"}, "released": 1} 9 } 10 }, 11 { 12 "$limit": 10 13 }, 14 { 15 "$project": { 16 "_id": 0, 17 "title": 1, 18 "released": 1, 19 "paginationToken" : { "$meta" : "searchSequenceToken" }, 20 "score": {$meta: "searchScore"} 21 } 22 } 23 ])
1 [ 2 { 3 title: 'War', 4 released: ISODate('2002-03-14T00:00:00.000Z'), 5 paginationToken: 'CMFRGgYQup3BhQgaCSkAQCKS7AAAAA==', 6 score: 3.3774025440216064 7 }, 8 { 9 title: 'War', 10 released: ISODate('2014-09-21T00:00:00.000Z'), 11 paginationToken: 'CMelARoGELqdwYUIGgkpAAiClUgBAAA=', 12 score: 3.3774025440216064 13 }, 14 { 15 title: 'War Photographer', 16 paginationToken: 'CMBRGgYQuq+ngwgaAmAA', 17 score: 2.8268959522247314 18 }, 19 { 20 title: "Troma's War", 21 released: ISODate('1989-11-18T00:00:00.000Z'), 22 paginationToken: 'CL8kGgYQuq+ngwgaCSkAbP8QkgAAAA==', 23 score: 2.8268959522247314 24 }, 25 { 26 title: 'The War', 27 released: ISODate('1994-11-04T00:00:00.000Z'), 28 paginationToken: 'CI0wGgYQuq+ngwgaCSkAnIKEtgAAAA==', 29 score: 2.8268959522247314 30 }, 31 { 32 title: 'War Stories', 33 released: ISODate('1996-05-09T00:00:00.000Z'), 34 paginationToken: 'CPIyGgYQuq+ngwgaCSkA/DifwQAAAA==', 35 score: 2.8268959522247314 36 }, 37 { 38 title: "Gaston's War", 39 released: ISODate('1997-10-23T00:00:00.000Z'), 40 paginationToken: 'CMQ7GgYQuq+ngwgaCSkALPBSzAAAAA==', 41 score: 2.8268959522247314 42 }, 43 { 44 title: 'Shooting War', 45 released: ISODate('2000-12-07T00:00:00.000Z'), 46 paginationToken: 'CMJJGgYQuq+ngwgaCSkAOOhG4wAAAA==', 47 score: 2.8268959522247314 48 }, 49 { 50 title: "Varian's War", 51 released: ISODate('2001-04-22T00:00:00.000Z'), 52 paginationToken: 'CM5IGgYQuq+ngwgaCSkAGEkD5gAAAA==', 53 score: 2.8268959522247314 54 }, 55 { 56 title: "Hart's War", 57 released: ISODate('2002-02-15T00:00:00.000Z'), 58 paginationToken: 'CMtJGgYQuq+ngwgaCSkAjBYH7AAAAA==', 59 score: 2.8268959522247314 60 } 61 ]
注意
结果中文档的词元可能不同。 在运行searchAfter
或searchBefore
查询之前,将后续查询中的词元替换为 Atlas Search 在结果中返回的词元。
后续 searchAfter
和 searchBefore
查询
以下查询使用具有相同语义的另一个查询中的词元来检索指定词元之后或之前的分页结果。 如果您运行了示例searchSequenceToken
查询,结果中文档的令牌可能会有所不同。 请务必将本节中查询中的令牌替换为查询结果中返回的令牌。
查询使用了下列管道阶段:
$search
阶段来执行以下操作:从 Atlas Search 结果中搜索术语
war
在title
字段的文档。首先按分数对结果进行排序,然后按
released
字段的值对分数相同的文档进行升序排序。
$limit
阶段将结果限制为10
文档。$project
阶段来执行以下操作:在文档中仅包含
title
和released
字段。添加以下字段:
名为
paginationToken
的字段,其中包含每个文档的 Base64 编码词元。名为
score
的字段,包含每个文档的相关性分数。
参考点之后的Atlas Search
以下查询请求 Atlas Search 结果中在指定参考点之后包含title
字段中的war
一词的文档。 它使用与searchSequenceToken
查询结果中的最后一个文档关联的词元(在58行上)作为参考点来检索结果中的下一个10
文档。
1 db.movies.aggregate([ 2 { 3 "$search": { 4 "text": { 5 "path": "title", 6 "query": "war" 7 }, 8 "sort": {score: {$meta: "searchScore"}, "released": 1}, 9 "searchAfter": "CMtJGgYQuq+ngwgaCSkAjBYH7AAAAA==" 10 } 11 }, 12 { 13 "$limit": 10 14 }, 15 { 16 "$project": { 17 "_id": 0, 18 "title": 1, 19 "released": 1, 20 "paginationToken" : { "$meta" : "searchSequenceToken" }, 21 "score": { "$meta": "searchScore" } 22 } 23 } 24 ])
1 [ 2 { 3 title: 'The War', 4 released: ISODate('2007-09-23T00:00:00.000Z'), 5 paginationToken: 'CP9xGgYQuq+ngwgaCSkA1KkvFQEAAA==', 6 score: 2.8268959522247314 7 }, 8 { 9 title: 'War, Inc.', 10 released: ISODate('2008-06-13T00:00:00.000Z'), 11 paginationToken: 'COhuGgYQuq+ngwgaCSkAtDh/GgEAAA==', 12 score: 2.8268959522247314 13 }, 14 { 15 title: 'War, Inc.', 16 released: ISODate('2008-06-13T00:00:00.000Z'), 17 paginationToken: 'COluGgYQuq+ngwgaCSkAtDh/GgEAAA==', 18 score: 2.8268959522247314 19 }, 20 { 21 title: 'War Dance', 22 released: ISODate('2008-11-01T00:00:00.000Z'), 23 paginationToken: 'CONvGgYQuq+ngwgaCSkAYFlVHQEAAA==', 24 score: 2.8268959522247314 25 }, 26 { 27 title: 'War Horse', 28 released: ISODate('2011-12-25T00:00:00.000Z'), 29 paginationToken: 'CJWFARoGELqvp4MIGgkpAEyEcjQBAAA=', 30 score: 2.8268959522247314 31 }, 32 { 33 title: 'Cold War', 34 released: ISODate('2012-11-08T00:00:00.000Z'), 35 paginationToken: 'CJGUARoGELqvp4MIGgkpAPBQ3ToBAAA=', 36 score: 2.8268959522247314 37 }, 38 { 39 title: 'Drug War', 40 released: ISODate('2013-04-04T00:00:00.000Z'), 41 paginationToken: 'CMWTARoGELqvp4MIGgkpAMRX0j0BAAA=', 42 score: 2.8268959522247314 43 }, 44 { 45 title: 'War Story', 46 released: ISODate('2014-07-30T00:00:00.000Z'), 47 paginationToken: 'CJCdARoGELqvp4MIGgkpAPyQhEcBAAA=', 48 score: 2.8268959522247314 49 }, 50 { 51 title: 'A War', 52 released: ISODate('2015-09-10T00:00:00.000Z'), 53 paginationToken: 'CL2kARoGELqvp4MIGgkpAECNtE8BAAA=', 54 score: 2.8268959522247314 55 }, 56 { 57 title: 'War Pigs', 58 released: ISODate('2015-09-18T00:00:00.000Z'), 59 paginationToken: 'CJ6kARoGELqvp4MIGgkpACDA3U8BAAA=', 60 score: 2.8268959522247314 61 } 62 ]
参考点之前的Atlas Search
以下查询请求 Atlas Search 指定参考点之前的 title
字段中搜索词 war
的结果。它使用与样本 searchAfter
查询结果中最后一个文档相关联的词元(59 行)作为参考点,从结果中检索前面的 10
个文档。
1 db.movies.aggregate([ 2 { 3 "$search": { 4 "text": { 5 "path": "title", 6 "query": "war" 7 }, 8 "sort": {score: {$meta: "searchScore"}, "released": 1}, 9 "searchBefore": "CJ6kARoGELqvp4MIGgkpACDA3U8BAAA=" 10 } 11 }, 12 { 13 "$limit": 10 14 }, 15 { 16 "$project": { 17 "_id": 0, 18 "title": 1, 19 "released": 1, 20 "paginationToken" : { "$meta" : "searchSequenceToken" }, 21 "score": { "$meta": "searchScore" } 22 } 23 } 24 ])
1 [ 2 { 3 title: 'A War', 4 released: ISODate('2015-09-10T00:00:00.000Z'), 5 paginationToken: 'CL2kARoGELqvp4MIGgkpAECNtE8BAAA=', 6 score: 2.8268959522247314 7 }, 8 { 9 title: 'War Story', 10 released: ISODate('2014-07-30T00:00:00.000Z'), 11 paginationToken: 'CJCdARoGELqvp4MIGgkpAPyQhEcBAAA=', 12 score: 2.8268959522247314 13 }, 14 { 15 title: 'Drug War', 16 released: ISODate('2013-04-04T00:00:00.000Z'), 17 paginationToken: 'CMWTARoGELqvp4MIGgkpAMRX0j0BAAA=', 18 score: 2.8268959522247314 19 }, 20 { 21 title: 'Cold War', 22 released: ISODate('2012-11-08T00:00:00.000Z'), 23 paginationToken: 'CJGUARoGELqvp4MIGgkpAPBQ3ToBAAA=', 24 score: 2.8268959522247314 25 }, 26 { 27 title: 'War Horse', 28 released: ISODate('2011-12-25T00:00:00.000Z'), 29 paginationToken: 'CJWFARoGELqvp4MIGgkpAEyEcjQBAAA=', 30 score: 2.8268959522247314 31 }, 32 { 33 title: 'War Dance', 34 released: ISODate('2008-11-01T00:00:00.000Z'), 35 paginationToken: 'CONvGgYQuq+ngwgaCSkAYFlVHQEAAA==', 36 score: 2.8268959522247314 37 }, 38 { 39 title: 'War, Inc.', 40 released: ISODate('2008-06-13T00:00:00.000Z'), 41 paginationToken: 'COluGgYQuq+ngwgaCSkAtDh/GgEAAA==', 42 score: 2.8268959522247314 43 }, 44 { 45 title: 'War, Inc.', 46 released: ISODate('2008-06-13T00:00:00.000Z'), 47 paginationToken: 'COhuGgYQuq+ngwgaCSkAtDh/GgEAAA==', 48 score: 2.8268959522247314 49 }, 50 { 51 title: 'The War', 52 released: ISODate('2007-09-23T00:00:00.000Z'), 53 paginationToken: 'CP9xGgYQuq+ngwgaCSkA1KkvFQEAAA==', 54 score: 2.8268959522247314 55 }, 56 { 57 title: "Hart's War", 58 released: ISODate('2002-02-15T00:00:00.000Z'), 59 paginationToken: 'CMtJGgYQuq+ngwgaCSkAjBYH7AAAAA==', 60 score: 2.8268959522247314 61 } 62 ]
对于前面的查询,请注意 Atlas Search 结果是按倒序排列的。 以下查询使用$limit
阶段以及toArray()和reverse()
方法来构建类似于“上一页”的函数。
1 db.movies.aggregate([ 2 { 3 "$search": { 4 "text": { 5 "path": "title", 6 "query": "war" 7 }, 8 "sort": {score: {$meta: "searchScore"}, "released": 1}, 9 "searchBefore": "CJ6kARoGELqvp4MIGgkpACDA3U8BAAA=" 10 } 11 }, 12 { 13 "$limit": 10 14 }, 15 { 16 "$project": { 17 "_id": 0, 18 "title": 1, 19 "released": 1, 20 "paginationToken" : { "$meta" : "searchSequenceToken" }, 21 "score": { "$meta": "searchScore" } 22 } 23 } 24 ]).toArray().reverse()
1 [ 2 { 3 title: "Hart's War", 4 released: ISODate('2002-02-15T00:00:00.000Z'), 5 paginationToken: 'CMtJGgYQuq+ngwgaCSkAjBYH7AAAAA==', 6 score: 2.8268959522247314 7 }, 8 { 9 title: 'The War', 10 released: ISODate('2007-09-23T00:00:00.000Z'), 11 paginationToken: 'CP9xGgYQuq+ngwgaCSkA1KkvFQEAAA==', 12 score: 2.8268959522247314 13 }, 14 { 15 title: 'War, Inc.', 16 released: ISODate('2008-06-13T00:00:00.000Z'), 17 paginationToken: 'COhuGgYQuq+ngwgaCSkAtDh/GgEAAA==', 18 score: 2.8268959522247314 19 }, 20 { 21 title: 'War, Inc.', 22 released: ISODate('2008-06-13T00:00:00.000Z'), 23 paginationToken: 'COluGgYQuq+ngwgaCSkAtDh/GgEAAA==', 24 score: 2.8268959522247314 25 }, 26 { 27 title: 'War Dance', 28 released: ISODate('2008-11-01T00:00:00.000Z'), 29 paginationToken: 'CONvGgYQuq+ngwgaCSkAYFlVHQEAAA==', 30 score: 2.8268959522247314 31 }, 32 { 33 title: 'War Horse', 34 released: ISODate('2011-12-25T00:00:00.000Z'), 35 paginationToken: 'CJWFARoGELqvp4MIGgkpAEyEcjQBAAA=', 36 score: 2.8268959522247314 37 }, 38 { 39 title: 'Cold War', 40 released: ISODate('2012-11-08T00:00:00.000Z'), 41 paginationToken: 'CJGUARoGELqvp4MIGgkpAPBQ3ToBAAA=', 42 score: 2.8268959522247314 43 }, 44 { 45 title: 'Drug War', 46 released: ISODate('2013-04-04T00:00:00.000Z'), 47 paginationToken: 'CMWTARoGELqvp4MIGgkpAMRX0j0BAAA=', 48 score: 2.8268959522247314 49 }, 50 { 51 title: 'War Story', 52 released: ISODate('2014-07-30T00:00:00.000Z'), 53 paginationToken: 'CJCdARoGELqvp4MIGgkpAPyQhEcBAAA=', 54 score: 2.8268959522247314 55 }, 56 { 57 title: 'A War', 58 released: ISODate('2015-09-10T00:00:00.000Z'), 59 paginationToken: 'CL2kARoGELqvp4MIGgkpAECNtE8BAAA=', 60 score: 2.8268959522247314 61 } 62 ]