For AI agents: a documentation index is available at https://www.mongodb.com/zh-cn/docs/llms.txt — markdown versions of all pages are available by appending .md to any URL path.
Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
MongoDB Branding Shape
Click here >
Docs 菜单

facet (MongoDB搜索操作符)

facet

facet 收集器按指定分面字段中的值或范围对结果进行分组,并返回每个组的计数。

您可以将 facet$search$searchMeta 阶段一起使用。MongoDB 建议使用附带 $searchMeta 阶段的 facet 来仅检索查询的元数据结果。要使用 $search 阶段来检索元数据结果和查询结果,则须使用 $$SEARCH_META 聚合变量。要了解更多信息,请参阅 SEARCH_META 聚合变量

如果在 embeddedDocuments 字段类型定义中定义了 storedSource ,就可以使用 returnScope returnStoredSource 对对象数组内的嵌套字段进行分面。否则,您只能在根 embeddedDocuments 类型字段上进行分面。关于分面的示例:

facet 通过以下语法实现:

{
"$searchMeta"|"$search": {
"index": <index name>, // optional, defaults to "default"
"facet": {
"operator": {
<operator-specifications>
},
"facets": {
<facet-definitions>
}
},
"returnScope": {
"path": "<embedded-documents-field-to-query>"
},
"returnStoredSource": true
}
}
字段
类型
必需?
说明

facets

文档

用于对每个分面(Facet)的数据进行分桶的信息。您必须指定至少一个分面定义。

operator

文档

no

用于执行分面(Facet)面操作的操作符。如果省略, MongoDB搜索将对集合中的所有文档执行分面(Facet)。

分面(Facet)定义文档包含分面(Facet)名称和特定于分面(Facet)类型的选项。MongoDB Search 支持以下类型的分面:

重要

stringFacet 现已过时。请改用令牌,以改进分面(Facet)。

要详细了解分面(Facet)的更新和过时字段类型之间的区别,请参阅比较分面(Facet)的字段类型。

字符串分面允许您根据指定字符串字段中最常见的字符串值缩小MongoDB搜索结果的范围。 请注意,字符串字段必须作为词元进行索引。要对嵌入式文档中的字符串字段进行分面(Facet),您还必须将父字段作为文档类型索引。当您对数组或嵌入式文档中的分面(Facet)进行分面时, MongoDB Search 会根据匹配的根文档的数量返回分面(Facet)计数。

字符串分面采用以下语法:

{
"$searchMeta": {
"facet":{
"operator": {
<operator-specification>
},
"facets": {
"<facet-name>" : {
"type" : "string",
"path" : "<field-path>",
"numBuckets" : <number-of-categories>,
}
}
}
}
}
选项
类型
说明
必需?

numBuckets

int

结果中要返回的最大分面(Facet)面类别数。值必须小于或等于 1000。如果指定,如果数据分组的类别数量少于请求的数量, MongoDB搜索返回的类别数量可能会少于请求的数量。如果省略,则默认为 10,这意味着MongoDB Search 将仅返回按计数排列靠前的 10分面(Facet)类别。

no

path

字符串

用于分面的字段路径。您可将被索引字段指定为 token

type

字符串

分面类型。值必须是 string

例子

以下示例将对 sample_mflix.movies 集合使用名为 default 的索引。集合中的 genres 字段被索引为 token 类型,而 year 字段被索引为 number 类型。

{
"mappings": {
"dynamic": false,
"fields": {
"genres": {
"type": "token"
},
"year": {
"type": "number"
}
}
}
}

该查询使用 $searchMeta 阶段在 movies 集合中的 year 字段内搜索从 2000 年到 2015 年的电影,并检索每种类型的电影数量。

1db.movies.aggregate([
2 {
3 "$searchMeta": {
4 "facet": {
5 "operator": {
6 "range": {
7 "path": "year",
8 "gte": 2000,
9 "lte": 2015
10 }
11 },
12 "facets": {
13 "genresFacet": {
14 "type": "string",
15 "path": "genres"
16 }
17 }
18 }
19 }
20 }
21])
1[
2 {
3 count: { lowerBound: Long('12568') },
4 facet: {
5 genresFacet: {
6 buckets: [
7 { _id: 'Drama', count: Long('7079') },
8 { _id: 'Comedy', count: Long('3689') },
9 { _id: 'Romance', count: Long('1764') },
10 { _id: 'Thriller', count: Long('1584') },
11 { _id: 'Documentary', count: Long('1472') },
12 { _id: 'Action', count: Long('1471') },
13 { _id: 'Crime', count: Long('1367') },
14 { _id: 'Adventure', count: Long('1056') },
15 { _id: 'Horror', count: Long('866') },
16 { _id: 'Biography', count: Long('796') }
17 ]
18 }
19 }
20 }
21]

To learn more about these results, see Facet Results.

重要

numberFacet 现已过时。请改用令牌,以改进分面 (Facet)。

要详细了解分面(Facet)的更新和过时字段类型之间的区别,请参阅比较分面(Facet)的字段类型。

数字分面允许您将搜索结果分解为不同的数字范围,从而确定数字值在搜索结果中的频率。当您对数组或嵌入式文档中的数字进行分面(Facet)时, MongoDB Search 会根据匹配的根文档的数量返回分面(Facet)计数。

数字分面采用以下语法:

{
"$searchMeta": {
"facet":{
"operator": {
<operator-specification>
},
"facets": {
"<facet-name>" : {
"type" : "number",
"path" : "<field-path>",
"boundaries" : <array-of-numbers>,
"default": "<bucket-name>"
}
}
}
}
}
选项
类型
说明
必需?

boundaries

数字数组

按升序排列的数值列表,而这些值指定了每个存储桶的边界。您必须指定至少两个边界,而这些边界应小于或等于 1000 ([2, 1000])。每对相邻的值均会充当存储桶的包含下限和不含上限。您可以指定以下 BSON 类型的值的任意组合:

  • 32 位整数 (int32)

  • 64 位整数 (int64)

  • 64 位二进制浮点数 (double)

default

字符串

附加存储桶的名称,用于对从操作符返回的不属于指定边界的文档进行计数。如果省略, MongoDB Search 也会包含不属于指定存储桶的分面(Facet)操作符符的结果,但不将其包含在任何存储桶计数中。

no

path

字符串

用于分面的字段路径。您可以指定一个已建立 number 类型索引的字段。

type

字符串

分面类型。值必须是 number

例子

以下示例将对 sample_mflix.movies 集合使用名为 default 的索引。集合中的 year 字段被索引为 number 类型。

{
"mappings": {
"dynamic": false,
"fields": {
"year": [
{
"type": "number"
}
]
}
}
}

此查询使用 $searchMeta 阶段在 movies 集合中的 year 字段中搜索 19802000 年间的影片,并检索查询的元数据结果。此查询指定了三个存储桶:

  • 1980,包括此存储桶的下限

  • 19901980 存储桶的不含上限以及此存储桶的包含下限

  • 20001990存储桶的独占上限

该查询还会指定一个名为 otherdefault 存储桶,以便检索不属于任何指定边界的查询结果。

1db.movies.aggregate([
2 {
3 "$searchMeta": {
4 "facet": {
5 "operator": {
6 "range": {
7 "path": "year",
8 "gte": 1980,
9 "lte": 2000
10 }
11 },
12 "facets": {
13 "yearFacet": {
14 "type": "number",
15 "path": "year",
16 "boundaries": [1980,1990,2000],
17 "default": "other"
18 }
19 }
20 }
21 }
22 }
23])
1[
2 {
3 count: { lowerBound: Long('6095') },
4 facet: {
5 yearFacet: {
6 buckets: [
7 { _id: 1980, count: Long('1956') },
8 { _id: 1990, count: Long('3558') },
9 { _id: 'other', count: Long('581') }
10 ]
11 }
12 }
13 }
14]

To learn more about these results, see Facet Results.

重要

dateFacet 现已过时。请改用令牌,以改进分面 (Facet)。

要详细了解分面(Facet)的更新和过时字段类型之间的区别,请参阅比较分面(Facet)的字段类型。

日期分面允许您根据日期缩小搜索结果的范围。当您对数组或嵌入式文档中的日期进行分面(Facet)时, MongoDB Search 会根据匹配的根文档的数量返回分面(Facet)计数。

日期分面采用以下语法:

{
"$searchMeta": {
"facet":{
"operator": {
<operator-specification>
},
"facets": {
"<facet-name>" : {
"type" : "date",
"path" : "<field-path>",
"boundaries" : <array-of-dates>,
"default": "<bucket-name>"
}
}
}
}
}
选项
类型
说明
必需?

boundaries

数字数组

指定每个存储桶边界的日期值列表。您必须指定:

  • 至少两个边界,而它们应小于或等于 1000 ([2, 1000])

  • 值按升序排列,最早日期在最前面

每对相邻的值都充当存储桶的包含下限和不包含上限。

default

字符串

附加存储桶的名称,用于对从操作符返回的不属于指定边界的文档进行计数。如果省略, MongoDB Search 也会包含不属于指定存储桶的分面(Facet)操作符符的结果,但MongoDB Search 不会将这些结果包含在任何存储桶计数中。

no

path

字符串

用于分面的字段路径。您可将被索引字段指定为 date 类型。

type

字符串

分面类型。值必须是 date

例子

以下示例将对 sample_mflix.movies 集合使用名为 default 的索引。集合中的 released 字段将索引为 date 类型。

{
"mappings": {
"dynamic": false,
"fields": {
"released": [
{
"type": "date"
}
]
}
}
}

此查询使用 $searchMeta 阶段在 movies 集合中的 released 字段中搜索 20002015 年间的影片,并检索查询字符串的元数据结果。此查询指定了四个存储桶:

  • 2000-01-01,包括此存储桶的下限

  • 2005-01-012000-01-01 存储桶的不含上限以及此存储桶的包含下限

  • 2010-01-012005-01-01 存储桶的不含上限以及此存储桶的包含下限

  • 2015-01-012010-01-01存储桶的独占上限

该查询还会指定一个名为 otherdefault 存储桶,以便检索不属于任何指定边界的查询结果。

1db.movies.aggregate([
2 {
3 "$searchMeta": {
4 "facet": {
5 "operator": {
6 "range": {
7 "path": "released",
8 "gte": ISODate("2000-01-01T00:00:00.000Z"),
9 "lte": ISODate("2015-01-31T00:00:00.000Z")
10 }
11 },
12 "facets": {
13 "yearFacet": {
14 "type": "date",
15 "path": "released",
16 "boundaries": [ISODate("2000-01-01"), ISODate("2005-01-01"), ISODate("2010-01-01"), ISODate("2015-01-01")],
17 "default": "other"
18 }
19 }
20 }
21 }
22 }
23])
1[
2 {
3 count: { lowerBound: Long('11922') },
4 facet: {
5 yearFacet: {
6 buckets: [
7 {
8 _id: ISODate('2000-01-01T00:00:00.000Z'),
9 count: Long('3028')
10 },
11 {
12 _id: ISODate('2005-01-01T00:00:00.000Z'),
13 count: Long('3953')
14 },
15 {
16 _id: ISODate('2010-01-01T00:00:00.000Z'),
17 count: Long('4832')
18 },
19 { _id: 'other', count: Long('109') }
20 ]
21 }
22 }
23 }
24]

To learn more about these results, see Facet Results.

与过时的类型(stringFacetnumberFacetdateFacet)相比,更新的MongoDB搜索字段类型改进了支持分面(Facet)的功能。下表概述了功能上的主要区别:

分面(Facet)类别
更新的字段类型
过时的分面(Facet)类型
主要差异

字符串

stringFacet(已过时)

规范器支持token 类型支持转换分面(Facet)桶的规范器。示例,对于 normalizer: lowercase,“ADIDAS”和“adidas”计入同一存储桶,而 stringFacet 将它们视为单独的存储桶。

数值

numberFacet(已过时)

数组支持number 类型考虑分面(Facet)存储桶数组中的值。示例,具有数组值 [0, 10] 的文档同时计入存储桶 [1, 5][6, 10],而 numberFacet 完全忽略数组值。

Date

dateFacet(已过时)

数组支持date 类型考虑分面(Facet)存储桶数组中的值。示例,包含日期的数组值可以影响多个日期范围存储桶,而 dateFacet 会完全忽略数组值。

注意

当为同一字段定义过时和更新的字段类型时,过时的分面(Facet)类型优先。示例,如果为字段同时定义了 tokenstringFacet,分面(Facet)计算将使用 stringFacet 映射。

对于分面(Facet)查询, MongoDB Search 返回定义的分面(Facet)名称到结果中该分面(Facet)的存储桶大量的映射。分面(Facet)结果文档包含 buckets 选项,它是分面(Facet)结果存储桶的大量。大量中的每个分面(Facet)存储桶文档都包含以下字段:

选项
类型
说明

_id

对象

标识此方面存储桶的唯一标识符。此值与正在分面的数据类型相匹配。

count

int

此分面(Facet)存储桶中的文档计数。要学习;了解有关 count字段的更多信息,请参阅对MongoDB搜索结果进行计数。

MongoDB Search 允许您同时查看和选择同一分面(Facet)中的多个存储桶。通常,选择分面(Facet)中的存储桶会根据该选择筛选搜索结果,并更改所有分面的计数。

例子

假设 sample_airbnb.listings集合的索引定义指定了以下字段的分面:

  • cancellation_policy

  • room_type

  • accommodates

cancellation_policy分面(Facet)具有以下存储桶:

  • flexible

  • moderate

  • strict_14_with_grace_period

  • super_strict_30

  • super_strict_60

每个都有自己的结果计数。当您搜索moderate cancellation_policy 时,其他四个存储桶的计数将变为 0。此外,room_typeaccommodates 分面(Facet)中的存储桶计数减少为每个存储桶中也具有 flexible cancellation_policy 的结果数。

如果您需要更精细地控制分面如何影响搜索结果计数,请在分面查询中启用doesNotAffect属性启用多选分面。这些分面仍会过滤结果,但查询不会更改其结果计数。

例子

考虑对 sample_airbnb.listings 集合的查询,查找包含 moderate cancellation_policy 的文档。如果您指定 doesNotAffect 值为 cancellation_policy,则 cancellation_policy 分面中存储桶的计数不会改变,但其他分面的存储桶结果计数将减少为每个存储桶中也具有 moderate cancellation_policy 的结果数量。

有关更多信息,请参阅多选分面(Facet)示例。

最后,对于具有多个分面的使用案例,限制哪些其他过滤器影响给定分面可能很有用。您可以通过在任何过滤器的 doesNotAffect 属性中指定任何分面(包括其他字段上的分面)来实现此目的。这使您能够一眼看出哪些选择会更快或更慢地缩小选项范围。

例子

考虑对 sample_airbnb.listings集合查询accommodates 值为 3 的文档。如果您指定的 doesNotAffect 值为 cancellation_policy,则 room_type 存储桶的结果计数会减少到每个存储桶中的结果数,其中也可容纳 3 人,但 cancellation_policy 中存储桶的结果计数不受影响。

For more information, see the Inter-Facet Filter Exclusion example.

当您使用 $search 阶段运行查询时, MongoDB Search 会将元数据结果存储在 $$SEARCH_META 变量中,并仅返回搜索结果。您可以在所有支持的聚合管道阶段中使用 $$SEARCH_META 变量来查看$search查询的元数据结果。

只有同时需要搜索结果和元数据结果时,MongoDB 才建议使用 $$SEARCH_META 变量。否则,请使用:

  • $search 阶段以仅显示搜索结果。

  • $searchMeta 阶段以仅显式元数据结果。

适用以下限制:

  • 只能对单个字段运行分面查询。无法对字段群组运行分面查询。

The following examples use the sample data. The metadata results example demonstrates how to run a $searchMeta query with facet to retrieve only the metadata in the results. The metadata and search results example demonstrates how to run a $search query with facet and the $SEARCH_META aggregation variable to retrieve both the search and metadata results. The returnScope example demonstrates how to facet on nested fields in an array of objects dynamically indexed using the embeddedDocuments type.

完成教程中的上一个步骤并安装依赖项

sample_mflix.movies 集合上的索引定义为要索引的字段指定了以下内容:

字段名称
数据类型

directors

year

released

{
"mappings": {
"dynamic": false,
"fields": {
"directors": {
"type": "token"
},
"year": {
"type": "number"
},
"released": {
"type": "date"
}
}
}
}

以下查询搜索 2000 年 1 月 1 日至 2015 年 1 月 31 日之间上映的电影。它请求 directorsyear 字段的元数据。

1db.movies.aggregate([
2 {
3 "$searchMeta": {
4 "facet": {
5 "operator": {
6 "range": {
7 "path": "released",
8 "gte": ISODate("2000-01-01T00:00:00.000Z"),
9 "lte": ISODate("2015-01-31T00:00:00.000Z")
10 }
11 },
12 "facets": {
13 "directorsFacet": {
14 "type": "string",
15 "path": "directors",
16 "numBuckets" : 7
17 },
18 "yearFacet" : {
19 "type" : "number",
20 "path" : "year",
21 "boundaries" : [2000,2005,2010, 2015]
22 }
23 }
24 }
25 }
26 }
27])
1[
2 {
3 count: { lowerBound: Long('11922') },
4 facet: {
5 yearFacet: {
6 buckets: [
7 { _id: 2000, count: Long('3064') },
8 { _id: 2005, count: Long('4035') },
9 { _id: 2010, count: Long('4553') }
10 ]
11 },
12 directorsFacet: {
13 buckets: [
14 { _id: 'Takashi Miike', count: Long('26') },
15 { _id: 'Johnnie To', count: Long('20') },
16 { _id: 'Steven Soderbergh', count: Long('18') },
17 { _id: 'Michael Winterbottom', count: Long('16') },
18 { _id: 'Ridley Scott', count: Long('15') },
19 { _id: 'Tyler Perry', count: Long('15') },
20 { _id: 'Clint Eastwood', count: Long('14') }
21 ]
22 }
23 }
24 }
25]

结果显示 sample_mflix.movies 集合中的以下计数:

  • MongoDB搜索为查询返回的从 2000 年(含下边界)到 2015 年(不包括上边界)的电影数量

  • MongoDB搜索为查询返回的每位导演的电影数量

To learn more about these results, see Facet Results.

使用 $search 进行搜索,并使用 $$Search_meta 变量检索搜索结果和元数据结果。

sample_mflix.movies 集合上的索引定义为要索引的字段指定了以下内容:

字段名称
数据类型

genres

released

{
"mappings": {
"dynamic": false,
"fields": {
"genres": {
"type": "token"
},
"released": {
"type": "date"
}
}
}
}

以下查询使用 $search 阶段搜索 1999 年 7 月 01 上映的电影。该查询包括 $facet 阶段,用于使用以下子管道阶段处理输入文档:

  • $project 阶段,在 docs 输出字段中排除文件中除titlereleased 字段以外的所有字段

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

    • $search 阶段的输出限制为 2 个文档

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

    注意

    限制必须很小,结果才能适合 16 MB 的文档。

  • $replaceWith 阶段将存储在 $$SEARCH_META 变量中的元数据结果包含在 meta 输出字段中

该查询还包括用于添加 meta 字段的 $set 阶段。

注意

要查看以下查询的元数据结果, MongoDB Search 必须返回与查询匹配的文档。

1db.movies.aggregate([
2 {
3 "$search": {
4 "facet": {
5 "operator": {
6 "near": {
7 "path": "released",
8 "origin": ISODate("1999-07-01T00:00:00.000+00:00"),
9 "pivot": 7776000000
10 }
11 },
12 "facets": {
13 "genresFacet": {
14 "type": "string",
15 "path": "genres"
16 }
17 }
18 }
19 }
20 },
21 { "$limit": 2 },
22 {
23 "$facet": {
24 "docs": [
25 { "$project":
26 {
27 "title": 1,
28 "released": 1
29 }
30 }
31 ],
32 "meta": [
33 {"$replaceWith": "$$SEARCH_META"},
34 {"$limit": 1}
35 ]
36 }
37 },
38 {
39 "$set": {
40 "meta": {
41 "$arrayElemAt": ["$meta", 0]
42 }
43 }
44 }
45])
1[
2 {
3 docs: [
4 {
5 _id: ObjectId('573a1393f29313caabcde1ae'),
6 title: 'Begone Dull Care',
7 released: ISODate('1999-07-01T00:00:00.000Z')
8 },
9 {
10 _id: ObjectId('573a13a9f29313caabd2048a'),
11 title: 'Fara' released: ISODate('1999-07-01T00:00:00.000Z')
12 }
13 ],
14 meta: {
15 count: { lowerBound: Long('20878') },
16 facet: {
17 genresFacet: {
18 buckets: [
19 { _id: 'Drama', count: Long('12149') },
20 { _id: 'Comedy', count: Long('6436') },
21 { _id: 'Romance', count: Long('3274') },
22 { _id: 'Crime', count: Long('2429') },
23 { _id: 'Thriller', count: Long('2400') },
24 { _id: 'Action', count: Long('2349') },
25 { _id: 'Adventure', count: Long('1876') },
26 { _id: 'Documentary', count: Long('1755') },
27 { _id: 'Horror', count: Long('1432') },
28 { _id: 'Biography', count: Long('1244') }
29 ]
30 }
31 }
32 }
33 }
34]

To learn more about these results, see Facet Results.

使用分面在嵌入文档中,按照子字段进行分面搜索。

sample_training.companies 集合上的索引定义将 funding_rounds 字段作为 embeddedDocuments 类型进行索引。它动态索引 funding_rounds 对象数组中的所有字段,并通过 storedSource 选项将 raised_currency_coderaised_amount 字段存储在funding_rounds 数组中。

{
"mappings": {
"dynamic": false,
"fields": {
"funding_rounds": {
"type": "embeddedDocuments",
"dynamic": true,
"storedSource": {
"include": [
"raised_currency_code",
"raised_amount"
]
}
}
}
}
}

以下查询:

  • 使用 text(MongoDB Search 操作符)搜索在 USD 中筹集的资金。

  • 使用 returnScope 选项将查询上下文设置为名为 funding_roundsembeddedDocuments 字段。要使用 returnScope,查询:

    • 指定 returnStoredSource 选项,该选项是必需的,以返回存储的源字段。
  • funding_rounds 对象数组中 raised_amount 字段上的分面。此查询指定了三个存储桶:

    • 5000000,包括此存储桶的下限

    • 5250000,5000000 存储桶的不含上限以及此存储桶的包含下限

    • 5500000,5250000 存储桶的独占上限

1db.companies.aggregate([
2 {
3 "$searchMeta": {
4 "returnStoredSource": true,
5 "returnScope": {
6 "path": "funding_rounds"
7 },
8 "facet": {
9 "operator": {
10 "text": {
11 "path": "funding_rounds.raised_currency_code",
12 "query": "USD"
13 }
14 },
15 "facets": {
16 "raisedAmountFacet": {
17 "type": "number",
18 "path": "funding_rounds.raised_amount",
19 "boundaries": [5000000, 5250000, 5500000]
20 }
21 }
22 }
23 }
24 }
25])
1[
2 {
3 count: { lowerBound: Long('5329') },
4 facet: {
5 raisedAmountFacet: {
6 buckets: [
7 { _id: 5000000, count: Long('251') },
8 { _id: 5250000, count: Long('32') }
9 ]
10 }
11 }
12 }
13]

在前面的 MongoDB Search 结果中,分面计数基于嵌入的子文档,而不是父文档。

使用 doesNotAffect 进行搜索,以便更精细地控制分面(Facet)过滤器。

以下针对 sample_airbnb.listingsAndReviews 集合的索引定义会自动索引所有可动态索引的字段,并配置 cancellation_policyroom_typeprice 字段以进行分面搜索。

{
"mappings": {
"dynamic": false,
"fields": {
"cancellation_policy": {
"type": "token"
},
"room_type": {
"type": "token"
},
"accommodates": {
"type": "number"
}
}
}
}

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

  • cancellation_policyroomTypeaccommodates 字段上的分面。

    cancellation_policy分面(Facet)具有以下存储桶:

    • "strict_14_with_grace_period"

    • "moderate"

    • "flexible"

    • "super_strict_30"

    • "super_strict_60"

    room_type分面(Facet)具有以下存储桶:

    • "Entire home/apt"

    • "Private room"

    • "Shared room"

    该查询将 accommodates分面(Facet)划分为多个存储桶:

    • 1,包括此存储桶的下限

    • 21 存储桶的不含上限以及此存储桶的包含下限。

    • 42 存储桶的不含上限以及此存储桶的包含下限。

    • 84存储桶的独占上限

  • 对必须在 操作符 中包含文本 的列表执行compound 搜索,并在结果中 过滤器new york city description带有moderatecancellation_policy 的列表。doesNotAffect 设置可确保按 moderate cancellation_policy 进行筛选不会更改分面(Facet)中其他存储桶的计数; "strict_14_with_grace_period""flexible""super_strict_30""super_strict_60" 的计数为非零值。

1db.listingsAndReviews.aggregate([
2 {
3 $searchMeta: {
4 facet: {
5 facets: {
6 accommodatesFacet: {
7 path: "accommodates",
8 type: "number",
9 boundaries: [1,2,4,8],
10 },
11 cancellationFacet: {
12 path: "cancellation_policy",
13 type: "string",
14 },
15 roomTypeFacet: {
16 path: "room_type",
17 type: "string",
18 }
19 },
20 operator: {
21 compound: {
22 must: [
23 {
24 text: {
25 path: "description",
26 query: "new york city",
27 },
28 },
29 ],
30 filter: [
31 {
32 equals: {
33 path: "cancellation_policy",
34 value: "moderate",
35 doesNotAffect:
36 "cancellationFacet",
37 },
38 },
39 ],
40 },
41 },
42 },
43 }
44 },
45]
1[
2 {
3 count: { lowerBound: Long('531') },
4 facet: {
5 accomodatesFacet: {
6 buckets: [
7 { _id: "1", count: Long('25') },
8 { _id: "2", count: Long('270') },
9 { _id: "4", count: Long('204') },
10 ]
11 },
12 cancellationFacet: {
13 buckets: [
14 { _id: "strict_14_with_grace_period", count: Long('849') },
15 { _id: "moderate", count: Long('531') },
16 { _id: "flexible", count: Long('380') },
17 { _id: "super_strict_60", count: Long('25') }
18 { _id: "super_strict_30", count: Long('380') }
19 ]
20 },
21 roomTypeFacet: {
22 buckets: [
23 { _id: "Entire home/apt", count: Long('369') },
24 { _id: "Private room", count: Long('159') },
25 { _id: "Shared room", count: Long('3') },
26 ]
27 }
28 }
29 }
30]

请注意,尽管对 moderate 值进行了查询筛选条件,但 cancellationFacet 中的存储桶计数并未减为零。

在查询字段以外的分面上使用 doesNotAffect 进行搜索。

sample_airbnb.listingsAndReviews集合上的以下索引定义将为 cancellation_policyroom_typeprice 字段编制索引,从而对它们启用分面搜索。

{
"mappings": {
"dynamic": true,
"fields": {
"cancellation_policy": {
"type": "token"
},
"room_type": {
"type": "token"
},
"accommodates": {
"type": "number"
}
}
}
}

以下查询:

  • 搜索 description 中包含 new york city 文本且 cancellation_policymoderate 的列表。

  • cancellation_policyroomTypeaccommodates 字段上的分面。

    cancellation_policyroomType 分面均具有三个存储桶,分别对应于这些字段在集合中的三个唯一值。查询将 accommodates 分面分解为以下存储桶:

    • 1,包括此存储桶的下限

    • 21 存储桶的不含上限以及此存储桶的包含下限。

    • 42 存储桶的不含上限以及此存储桶的包含下限。

    • 84存储桶的独占上限

  • compound.filterequals操作符中的 doesNotAffect属性设置为 accommodatesFacet。这将从过滤中排除 accommodates分面(Facet)内的存储桶。因此,对 moderate cancellation_policy 进行筛选会减少 cancellation_policy分面(Facet)中其他存储桶的计数到 0,并减少 roomType分面(Facet)中存储桶的计数,但accommodates分面(Facet)未更改。这样,您就可以比较过滤器对不同分面的影响。

1db.listingsAndReviews.aggregate([
2 {
3 $searchMeta: {
4 facet: {
5 facets: {
6 accommodatesFacet: {
7 path: "accommodates",
8 type: "number",
9 boundaries: [1,2,4,8],
10 },
11 cancellationFacet: {
12 path: "cancellation_policy",
13 type: "string",
14 },
15 roomTypeFacet: {
16 path: "room_type",
17 type: "string",
18 }
19 },
20 operator: {
21 compound: {
22 must: [
23 {
24 text: {
25 path: "description",
26 query: "new york city",
27 },
28 },
29 ],
30 filter: [
31 {
32 equals: {
33 path: "cancellation_policy",
34 value: "moderate",
35 doesNotAffect:
36 "accommodatesFacet",
37 },
38 },
39 ],
40 },
41 },
42 },
43 },
44 },
45]
1[
2 {
3 count: { lowerBound: Long('531') },
4 facet: {
5 accomodatesFacet: {
6 buckets: [
7 { _id: "1", count: Long('25') },
8 { _id: "2", count: Long('270') },
9 { _id: "4", count: Long('204') },
10 ]
11 },
12 cancellationFacet: {
13 buckets: [
14 { _id: "flexible", count: Long('XXX') },
15 { _id: "moderate", count: Long('531') },
16 { _id: "strict_14_with_grace_period", count: Long('XXX') },
17 ]
18 },
19 roomTypeFacet: {
20 buckets: [
21 { _id: "Entire home/apt", count: Long('369') },
22 { _id: "Private room", count: Long('159') },
23 { _id: "Shared room", count: Long('3') },
24 ]
25 }
26 }
27 }
28]

要学习;了解更多信息,请参阅如何在MongoDB Search 中使用分面。

facet您可以通过我们的课程和视频,学习;了解有关MongoDB搜索中的 ( MongoDB搜索操作符)的更多信息。

要学习;了解有关在MongoDB Search 中使用分面的更多信息,请学习MongoDB University的MongoDB简介课程的 9 单元。1.5 小时单元包括MongoDB Search 概述以及有关创建MongoDB Search 索引、使用复合运算符运行$search 查询以及使用 facet 对结果进行分组的课程。

观看此视频,学习;了解如何在查询中创建和使用数字和字符串 facet(MongoDB搜索运算符),对结果进行群组并检索分组中的结果计数。

时长:11 分钟