facet
定义
facet
facet
收集器按指定分面字段中的值或范围对结果进行分组,并返回每个组的计数。您可以将
facet
与 和$search
$searchMeta
阶段一起使用。MongoDB建议使用facet
$searchMeta
和 阶段来检索仅针对该查询的元数据结果。要使用 阶段检索元数据结果和查询结果,必须使用$search
$$SEARCH_META
聚合变量。请参阅SEARCH_META
聚合变量以学习;了解详情。
限制
您不能使用 explain 运行 facet
查询。
语法
facet
通过以下语法实现:
{ "$searchMeta"|"$search": { "index": <index name>, // optional, defaults to "default" "facet": { "operator": { <operator-specifications> }, "facets": { <facet-definitions> } } } }
字段
字段 | 类型 | 必需? | 说明 |
---|---|---|---|
| 文档 | 是 | 用于对每个分面(Facet)的数据进行分桶的信息。您必须指定至少一个分面定义。 |
| 文档 | no | 用于执行分面操作的操作符。如省略,Atlas Search 将对集合中的所有文档执行分面操作。 |
分面定义
分面定义文档包含分面名称和特定于分面类型的选项。Atlas Search 支持以下类型的分面:
字符串分面
字符串分面允许您根据指定字符串字段中最常见的字符串值缩小Atlas Search结果的范围。请注意,字符串字段的索引必须为 stringFacet 。要对嵌入式文档中的字符串字段分面(Facet),您还必须将父字段作为文档类型索引。当您对数组或嵌入式文档中的字符串进行分面(Facet)面时, Atlas Search会根据匹配的根文档的数量返回分面(Facet)计数。
语法
字符串分面采用以下语法:
{ "$searchMeta": { "facet":{ "operator": { <operator-specification> }, "facets": { "<facet-name>" : { "type" : "string", "path" : "<field-path>", "numBuckets" : <number-of-categories>, } } } } }
选项
选项 | 类型 | 说明 | 必需? |
---|---|---|---|
| int | 结果中要返回的最大分面类别数量。值必须小于或等于 | no |
| 字符串 | 用于分面的字段路径。您可以指定一个已建立 stringFacet 索引的字段。 | 是 |
| 字符串 | 分面类型。值必须是 | 是 |
例子
例子
以下示例将对 sample_mflix.movies
集合使用名为 default
的索引。集合中的 genres
字段被索引为 stringFacet 类型,而 year
字段被索引为 number 类型。
{ "mappings": { "dynamic": false, "fields": { "genres": { "type": "stringFacet" }, "year": { "type": "number" } } } }
该查询使用 $searchMeta
阶段在 movies
集合中的 year
字段内搜索从 2000 年到 2015 年的电影,并检索每种类型的电影数量。
1 db.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 ]
要了解有关这些结果的更多信息,请参阅分面结果。
数值分面
重要
numberFacet 现已弃用。请改用数字。
数字分面允许您将搜索结果分解为不同的数字范围,从而确定数字值在搜索结果中的频率。当您对数组或嵌入式文档中的数字进行分面(Facet)时, Atlas Search会根据匹配的根文档的数量返回分面(Facet)计数。
语法
数字分面采用以下语法:
{ "$searchMeta": { "facet":{ "operator": { <operator-specification> }, "facets": { "<facet-name>" : { "type" : "number", "path" : "<field-path>", "boundaries" : <array-of-numbers>, "default": "<bucket-name>" } } } } }
选项
选项 | 类型 | 说明 | 必需? |
---|---|---|---|
| 数字数组 | 按升序排列的数值列表,用于指定每个存储桶的边界。您必须指定至少两个边界,且边界值小于或等于 1000 (
| 是 |
| 字符串 | 附加存储桶的名称,它可用于对从操作符返回的不属于指定边界的文档进行计数。如果省略,Atlas Search 还会包含不属于指定存储桶的分面运算符的结果,但不将其包含在任何存储桶计数中。 | no |
| 字符串 | 是 | |
| 字符串 | 分面类型。值必须是 | 是 |
例子
例子
以下示例使用default
sample_mflix.movies
集合上名为 的索引。集合中的year
字段被索引为数字类型。
{ "mappings": { "dynamic": false, "fields": { "year": [ { "type": "number" } ] } } }
此查询使用 $searchMeta
阶段在 movies
集合中的 year
字段中搜索 1980
到 2000
年间的影片,并检索查询的元数据结果。此查询指定了三个存储桶:
1980
,包括此存储桶的下限1990
、1980
存储桶的不含上限以及此存储桶的包含下限2000
,1990
存储桶的独占上限
该查询还会指定一个名为 other
的 default
存储桶,以便检索不属于任何指定边界的查询结果。
1 db.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)时, Atlas Search会根据匹配的根文档的数量返回分面(Facet)计数。
语法
日期分面采用以下语法:
{ "$searchMeta": { "facet":{ "operator": { <operator-specification> }, "facets": { "<facet-name>" : { "type" : "date", "path" : "<field-path>", "boundaries" : <array-of-dates>, "default": "<bucket-name>" } } } } }
选项
选项 | 类型 | 说明 | 必需? |
---|---|---|---|
| 数字数组 | 指定每个存储桶边界的日期值列表。您必须指定:
每对相邻的值都充当存储桶的包含下限和不包含上限。 | 是 |
| 字符串 | 附加存储桶的名称,它可用于对从操作符返回的不属于指定边界的文档进行计数。如果省略,Atlas Search 也会包含不属于指定存储桶的分面运算符的结果,但 Atlas Search 不会将这些结果包含在任何存储桶计数中。 | no |
| 字符串 | 是 | |
| 字符串 | 分面类型。值必须是 | 是 |
例子
例子
以下示例使用default
sample_mflix.movies
集合上名为 的索引。集合中的released
字段被索引为日期类型。
{ "mappings": { "dynamic": false, "fields": { "released": [ { "type": "date" } ] } } }
此查询使用 $searchMeta
阶段在 movies
集合中的 released
字段中搜索 2000
到 2015
年间的影片,并检索查询字符串的元数据结果。此查询指定了四个存储桶:
2000-01-01
,包括此存储桶的下限2005-01-01
、2000-01-01
存储桶的不含上限以及此存储桶的包含下限2010-01-01
、2005-01-01
存储桶的不含上限以及此存储桶的包含下限2015-01-01
,2010-01-01
存储桶的独占上限
该查询还会指定一个名为 other
的 default
存储桶,以便检索不属于任何指定边界的查询结果。
1 db.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 ]
要了解有关这些结果的更多信息,请参阅分面结果。
分面结果
对于分面查询,Atlas Search 返回定义的分面名称与结果中该分面的存储桶数组的映射。分面结果文档包含 buckets
选项,此选项是分面结果存储桶的数组。数组中的每个分面存储桶文档都包含以下字段:
选项 | 类型 | 说明 |
---|---|---|
| 对象 | 标识此方面存储桶的唯一标识符。此值与正在分面的数据类型相匹配。 |
| int | 此分面存储桶中的文档计数。要了解有关 |
SEARCH_META
聚合变量
当您使用 $search
阶段运行查询时,Atlas Search 会将元数据结果存储在 $$SEARCH_META
变量中,并且仅返回搜索结果。您可以在所有支持的聚合管道阶段使用 $$SEARCH_META
变量来查看 $search
查询的元数据结果。
只有同时需要搜索结果和元数据结果时,MongoDB 才建议使用 $$SEARCH_META
变量。否则,请使用:
$search
阶段以仅显示搜索结果。$searchMeta
阶段以仅显式元数据结果。
限制
适用以下限制:
只能对单个字段运行分面查询。无法对字段群组运行分面查询。
只能在运行 MongoDB v6.0 的集群上对分片集合运行分面查询。
示例
以下示例使用 sample_mflix.movies
集合。元数据结果示例演示如何使用 facet
运行 $searchMeta
查询,以便仅检索结果中的元数据。元数据和搜索结果示例演示了如何使用 facet
和 $SEARCH_META
聚合变量运行 $search
查询,以便检索搜索结果和元数据结果。
索引定义为要索引的字段指定了以下内容:
字段名称 | 数据类型 |
---|---|
| |
| |
|
{ "mappings": { "dynamic": false, "fields": { "directors": { "type": "stringFacet" }, "year": { "type": "number" }, "released": { "type": "date" } } } }
以下查询搜索 2000 年 1 月 1 日至 2015 年 1 月 31 日之间上映的电影。它请求 directors
和 year
字段的元数据。
1 db.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
集合中的以下计数:
Atlas Search 为查询返回的从 2000 年(含下限)到 2015 年(不含上限)的电影数量
Atlas Search 为查询返回的每位导演的电影数量
索引定义为要索引的字段指定了以下内容:
字段名称 | 数据类型 |
---|---|
| |
|
{ "mappings": { "dynamic": false, "fields": { "genres": { "type": "stringFacet" }, "released": { "type": "date" } } } }
以下查询使用 $search
阶段搜索 1999 年 7 月 01 上映的电影。该查询包括 $facet
阶段,用于使用以下子管道阶段处理输入文档:
$project
阶段,在docs
输出字段中排除文件中除title
和released
字段以外的所有字段$limit
阶段来执行以下操作:将
$search
阶段的输出限制为2
个文档在
meta
输出字段中将输出限制为1
个文档。
注意
限制必须很小,结果才能适合 16 MB 的文档。
$replaceWith
阶段将存储在$$SEARCH_META
变量中的元数据结果包含在meta
输出字段中
该查询还包括用于添加 meta
字段的 $set
阶段。
注意
要查看以下查询的元数据结果,Atlas Search 必须返回与该查询匹配的文档。
1 db.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', 12 released: ISODate('1999-07-01T00:00:00.000Z') 13 } 14 ], 15 meta: { 16 count: { lowerBound: Long('20878') }, 17 facet: { 18 genresFacet: { 19 buckets: [ 20 { _id: 'Drama', count: Long('12149') }, 21 { _id: 'Comedy', count: Long('6436') }, 22 { _id: 'Romance', count: Long('3274') }, 23 { _id: 'Crime', count: Long('2429') }, 24 { _id: 'Thriller', count: Long('2400') }, 25 { _id: 'Action', count: Long('2349') }, 26 { _id: 'Adventure', count: Long('1876') }, 27 { _id: 'Documentary', count: Long('1755') }, 28 { _id: 'Horror', count: Long('1432') }, 29 { _id: 'Biography', count: Long('1244') } 30 ] 31 } 32 } 33 } 34 } 35 ]
要了解有关这些结果的更多信息,请参阅分面结果。