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

对结果进行分页

在此页面上

  • 使用
  • Considerations
  • 检索参考点
  • 语法
  • 输出
  • 特定参考点后的Atlas Search
  • searchAfter 语法
  • 输出
  • 特定参考点之前的Atlas Search
  • searchBefore 语法
  • searchBefore 输出
  • 示例
  • searchSequenceToken 查询
  • 后续searchAftersearchBefore查询

在运行 MongoDB 6.0.13 + 或7.0.5 + 的Atlas 集群上,使用 Atlas Search 在参考点之后或之前按顺序检索 $search 查询结果。您可以使用 $search searchAftersearchBefore 选项按顺序遍历结果,并在应用程序中构建“下一页”和“上一页”功能。

要检索分页结果,请执行以下步骤:

  1. 在要查询的字段上创建索引

  2. 运行 $search 查询,返回一个参考点。要了解更多信息,请参阅 检索参考点。

  3. 在随后的 $search 查询中使用参考点来检索结果中的下一组或上一组文档。

    • 要了解有关检索结果以构建“下一页”函数的更多信息,请参阅特定参考点后的Atlas Search 。

    • 要了解有关检索结果以构建“上一页”函数的更多信息,请参阅特定参考点之前的Atlas Search 。

    • 要跳转到结果中的某个页面,请将 $skip$limit$search searchAftersearchBefore 选项相结合。例如,要从第 3 页跳转到第 5 页的结果,每页 10 个结果,请执行以下操作:

      1. 使用searchAfter和第3页上最后一个结果的引用点(结果30 )来检索结果。

      2. 使用$skip跳过第4页上的10结果(结果31 - 40 ),并使用$limit将结果限制为10文档。

      3. 返回第 5 页的结果(结果 41-50)。

      此处,使用 $skipsearchAfter选项可优化查询,只跳过 1 页结果(10 个文档)。相比之下,如果使用 $skip 而不使用 $search searchAfter 选项,查询将跳过 4 页结果( 40 个文档)。要了解更多信息,请参阅使用 searchAfter$skip从第 2 页跳转到第 5 页。

如果您在初始查询和后续查询之间更新集合,Atlas Search 会在后续查询结果中反映这些更新。

例如,假设您按updated_time字段对结果进行排序。 如果在第一个查询和后续查询之间更新文档,则同一个文档可能会出现在这两个查询结果中。 为避免这种情况,请按不可变字段对结果进行排序。

默认情况下,Atlas Search 按文档的相关性分数对结果中的文档进行排序。 如果结果中的多个文档具有相同分数,Atlas Search 将返回任意排序的结果。 要按确定的顺序返回文档,请使用唯一字段对查询结果进行排序。

注意

不同的搜索节点上,每个节点都有自己的带有不同内部 ID 的文档副本,当多个文档的分数相同时,Lucene 会使用该副本对结果进行排序。如果不处理查询的节点上文档的内部 ID 的分页顺序大于分页标记,则如果对结果进行排序和分页,处理查询的节点上的 mongot 可能会将其包含在结果中。为避免出现这种情况,请在 $search 之后使用 $match,并通过其 _id 排除该文档。

要了解如何按不可变或唯一字段对查询结果进行排序,请参阅对 Atlas Search 结果进行排序

要检索某个点的查询结果,必须在 $search 查询中提供参考点。您可以在 $search 阶段之后的 $project 阶段中使用 $meta 关键字 searchSequenceToken 来检索参考点。

searchSequenceToken 语法
1[{
2 "$search": {
3 "index": "<index-name>",
4 "<operator-name>"|"<collector-name>": {
5 <operator-specification>|<collector-specification>
6 }
7 ...
8 },
9 {
10 "$project": {
11 { "paginationToken" : { "$meta" : "searchSequenceToken" } }
12 },
13 ...
14}]

searchSequenceToken为结果中的每个文档生成一个基本64编码的词元。 令牌的长度随着查询的排序选项中指定的字段数量的增加而增加。 令牌不与数据库快照绑定。

除非在查询中指定 sort 选项,否则结果中的文档将按默认顺序排序。要了解如何对结果进行排序,请参阅对 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 ...
9 },
10 "$project": {
11 { "paginationToken" : { "$meta" : "searchSequenceToken" } }
12 },
13 ...
14}

Atlas Search 返回结果中指定词元之后的文档。 Atlas SearchsearchSequenceToken $project$search11在结果中返回为文档生成的词元,因为您在 阶段之后的 阶段中指定了 (如第 行所示)。这些词元可用作具有相同语义的另一个查询的参考点。

除非在查询中指定 sort 选项,否则结果中的文档将按默认顺序排序。要了解如何对结果进行排序,请参阅对 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 ...
9 },
10 "$project": {
11 { "paginationToken" : { "$meta" : "searchSequenceToken" } }
12 },
13 ...
14}

Atlas Search 以相反的顺序返回结果中指定标记之前的文档。Atlas Search 还会返回结果中文档的生成标记,因为您在 $search 阶段之后的 $project 阶段中指定了 searchSequenceToken(如 11 行所示)。这些标记可以用作具有相同语义的另一个查询的参考点。

以下示例使用 sample-mflix.movies 集合,该集合具有名为 default 的带有动态映射的 Atlas Search 索引。如果加载集合并创建索引,则可以对该集合运行以下查询。

以下查询使用以下管道阶段:

  • $search 以执行以下操作:

    • Atlas Search在集合的 title 字段中搜索术语 war

    • 首先按分数对结果进行排序,然后按released字段的值对分数相同的文档进行升序排序。

  • $limit阶段将结果限制为10文档。

  • $project 阶段来执行以下操作:

    • 仅包含 titlereleased 字段。

    • 添加以下字段:

      • 名为 paginationToken 的字段,其中包含每个文档的 Base64 编码词元。

      • 名为score的字段,包含每个文档的相关性分数。

1db.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]

注意

结果中文档的词元可能不同。 在运行searchAftersearchBefore查询之前,将后续查询中的词元替换为 Atlas Search 在结果中返回的词元。

以下查询使用具有相同语义的另一个查询中的词元来检索指定词元之后或之前的分页结果。 如果您运行了示例searchSequenceToken查询,结果中文档的令牌可能会有所不同。 请务必将本节中查询中的令牌替换为查询结果中返回的令牌。

查询使用了下列管道阶段:

  • $search 阶段来执行以下操作:

    • 从 Atlas Search 结果中搜索术语 wartitle 字段的文档。

    • 首先按分数对结果进行排序,然后按released字段的值对分数相同的文档进行升序排序。

  • $limit阶段将结果限制为10文档。

  • $project 阶段来执行以下操作:

    • 在文档中仅包含 titlereleased 字段。

    • 添加以下字段:

      • 名为 paginationToken 的字段,其中包含每个文档的 Base64 编码词元。

      • 名为score的字段,包含每个文档的相关性分数。

以下查询请求 Atlas Search 结果中在指定参考点之后包含title字段中的war一词的文档。 它使用与searchSequenceToken查询结果中的最后一个文档关联的词元(在58行上)作为参考点来检索结果中的下一个10文档。

1db.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 指定参考点之前title 字段中搜索词 war 的结果。它使用与样本 searchAfter 查询结果中最后一个文档相关联的词元(59 行)作为参考点,从结果中检索前面的 10 个文档。

1db.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()方法来构建类似于“上一页”的函数。

1db.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]

后退

4。对结果进行计数