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建议使用 和facet $searchMeta阶段来检索仅针对该查询的元数据结果。要使用 阶段检索元数据结果和查询结果,必须使用$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 支持以下类型的分面:

重要

dateFacet 现已过时。请改用日期,这样可以改进分面(Facet)。

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

ortant>

字符串分面允许您根据指定字符串字段中最常见的字符串值缩小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]

要学习;了解有关这些结果的更多信息,请参阅分面结果。

重要

dateFacet 现已过时。请改用日期,这样可以改进分面(Facet)。

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

ortant>

数字分面允许您将搜索结果分解为不同的数字范围,从而确定数字值在搜索结果中的频率。当您对数组或嵌入式文档中的数字进行分面(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]

要学习;了解有关这些结果的更多信息,请参阅分面结果。

重要

dateFacet 现已过时。请改用日期,这样可以改进分面(Facet)。

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

ortant>

日期分面允许您根据日期缩小搜索结果的范围。当您对数组或嵌入式文档中的日期进行分面(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]

要学习;了解有关这些结果的更多信息,请参阅分面结果。

与过时的类型(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 中存储桶的结果计数不受影响。

有关更多信息,请参阅分面筛选器排除示例。

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

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

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

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

适用以下限制:

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

以下示例使用示例数据。元数据结果示例演示如何使用 $searchMeta 运行 facet 查询,以便仅检索结果中的元数据。元数据和搜索结果示例演示了如何使用 facet$SEARCH_META 聚合变量运行 $search 查询,以便检索搜索结果和元数据结果。returnScope 示例演示了如何在使用 embeddedDocuments 类型动态索引的对象数组中对嵌套字段进行分面。

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

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搜索为查询返回的每位导演的电影数量

要学习;了解有关这些结果的更多信息,请参阅分面结果。

使用 $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]

要学习;了解有关这些结果的更多信息,请参阅分面结果。

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

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 分钟