facet
兼容性
facet
仅适用于运行以下版本之一的 Atlas 集群:
MongoDB 5.0.4+
MongoDB 6.0+
MongoDB 7.0+
注意
要对分片集合运行分面(Facet)查询,集群必须运行 MongoDB v6.0 或更高版本。
您不能使用 explain 运行 facet
查询。
定义
facet
facet
收集器按指定分面字段中的值或范围对结果进行分组,并返回每个组的计数。您可以将
facet
与$search
和$searchMeta
阶段一起使用。MongoDB 建议使用附带$searchMeta
阶段的facet
来仅检索查询的元数据结果。要使用$search
阶段来检索元数据结果和查询结果,必须使用$$SEARCH_META
聚合变量。请参阅SEARCH_META
聚合变量以了解更多信息。
语法
facet
通过以下语法实现:
{ "$searchMeta"|"$search": { "index": <index name>, // optional, defaults to "default" "facet": { "operator": { <operator-specifications> }, "facets": { <facet-definitions> } } } }
字段
分面定义
分面定义文档包含分面名称和特定于分面类型的选项。Atlas Search 支持以下类型的分面:
字符串分面
字符串分面允许您根据指定字符串字段中最常见的字符串值缩小 Atlas Search 结果的范围。请注意,字符串字段必须建立索引为 stringFacet。要对嵌入式文档中的字符串字段进行分面,您还必须对要作为文档类型的父字段进行索引。
注意
当您在嵌入式文档中对字符串字段进行分面时,Atlas Search 只返回与父文档数量匹配的分面计数。
语法
字符串分面采用以下语法:
{ "$searchMeta": { "facet":{ "operator": { <operator-specification> }, "facets": { "<facet-name>" : { "type" : "string", "path" : "<field-path>", "numBuckets" : <number-of-categories>, } } } } }
选项
选项 | 类型 | 说明 | 必需? |
---|---|---|---|
numBuckets | int | 结果中要返回的最大分面类别数量。值必须小于或等于 1000 。如果指定,如果数据分组的类别数量少于请求的数量,Atlas Search 返回的类别数量可能会少于请求的数量。如果省略,则默认为 10 ,这意味着 Atlas Search 将仅返回按计数排列靠前的 10 分面类别。 | no |
path | 字符串 | 用于分面的字段路径。您可以指定一个已建立 stringFacet 索引的字段。 | 是 |
type | 字符串 | 分面类型。值必须是 string 。 | 是 |
例子
例子
以下示例将对 sample_mflix.movies
集合使用名为 default
的索引。集合中的 genres
字段被索引为 stringFacet 类型,而 year
字段被索引为 number 类型。
{ "mappings": { "dynamic": false, "fields": { "genres": { "type": "stringFacet" }, "year": { "type": "number" } } } }
该查询使用 $searchMeta
阶段在 movies
集合中的 year
字段内搜索从 2000 年到 2015 年的电影,并检索每种类型的电影数量。
db.movies.aggregate([ { "$searchMeta": { "facet": { "operator": { "range": { "path": "year", "gte": 2000, "lte": 2015 } }, "facets": { "genresFacet": { "type": "string", "path": "genres" } } } } } ])
此查询将返回以下结果:
[ { count: { lowerBound: Long("13718") }, facet: { genresFacet: { buckets: [ { _id: 'Drama', count: Long("7759") }, { _id: 'Comedy', count: Long("3937") }, { _id: 'Romance', count: Long("1916") }, { _id: 'Thriller', count: Long("1705") }, { _id: 'Documentary', count: Long("1703") }, { _id: 'Action', count: Long("1558") }, { _id: 'Crime', count: Long("1475") }, { _id: 'Adventure', count: Long("1111") }, { _id: 'Horror', count: Long("1008") }, { _id: 'Biography', count: Long("877") } ] } } } ]
要了解有关这些结果的更多信息,请参阅分面结果。
数值分面
通过将搜索结果分成不同的数字范围,数字分面可以确定数值在搜索结果中的出现频率。
注意
限制
您无法对嵌入式文档中的数字字段进行分面处理。
语法
数字分面采用以下语法:
{ "$searchMeta": { "facet":{ "operator": { <operator-specification> }, "facets": { "<facet-name>" : { "type" : "number", "path" : "<field-path>", "boundaries" : <array-of-numbers>, "default": "<bucket-name>" } } } } }
选项
选项 | 类型 | 说明 | 必需? |
---|---|---|---|
boundaries | 数字数组 | 按升序排列的数值列表,这些值指定了每个桶的边界。您必须指定至少两个边界。每对相邻的值均会充当桶的包含下限和不含上限。您可以指定以下 BSON 类型的值的任意组合:
| 是 |
default | 字符串 | 附加存储桶的名称,它可用于对从操作符返回的不属于指定边界的文档进行计数。如果省略,Atlas Search 还会包含不属于指定存储桶的分面运算符的结果,但不将其包含在任何存储桶计数中。 | no |
path | 字符串 | 用于分面的字段路径。您可以指定一个已建立 numberFacet 类型索引的字段。 | 是 |
type | 字符串 | 分面类型。值必须是 number 。 | 是 |
例子
例子
以下示例将对 sample_mflix.movies
集合使用名为 default
的索引。集合中的 year
字段被索引为 numberFacet 和数字类型。
{ "mappings": { "dynamic": false, "fields": { "year": [ { "type": "numberFacet" }, { "type": "number" } ] } } }
此查询使用 $searchMeta
阶段在 movies
集合中的 year
字段中搜索 1980
到 2000
年间的影片,并检索查询的元数据结果。此查询指定了三个存储桶:
1980
,包括此存储桶的下限1990
、1980
存储桶的不含上限以及此存储桶的包含下限2000
,1990
存储桶的独占上限
该查询还会指定一个名为 other
的 default
存储桶,以便检索不属于任何指定边界的查询结果。
db.movies.aggregate([ { "$searchMeta": { "facet": { "operator": { "range": { "path": "year", "gte": 1980, "lte": 2000 } }, "facets": { "yearFacet": { "type": "number", "path": "year", "boundaries": [1980,1990,2000], "default": "other" } } } } } ])
此查询将返回以下结果:
[ { count: { lowerBound: Long('6095') }, facet: { yearFacet: { buckets: [ { _id: 1980, count: Long('1956') }, { _id: 1990, count: Long('3558') }, { _id: 'other', count: Long('581') } ] } } } ]
要了解有关这些结果的更多信息,请参阅分面结果。
日期分面
日期分面可以让您根据日期缩小搜索结果的范围。
注意
限制
您不能对嵌入式文档中的日期字段进行分面处理。
语法
日期分面采用以下语法:
{ "$searchMeta": { "facet":{ "operator": { <operator-specification> }, "facets": { "<facet-name>" : { "type" : "date", "path" : "<field-path>", "boundaries" : <array-of-dates>, "default": "<bucket-name>" } } } } }
选项
选项 | 类型 | 说明 | 必需? |
---|---|---|---|
boundaries | 数字数组 | 指定每个存储桶边界的日期值列表。您必须指定:
每对相邻的值都充当存储桶的包含下限和不包含上限。 | 是 |
default | 字符串 | 附加存储桶的名称,它可用于对从操作符返回的不属于指定边界的文档进行计数。如果省略,Atlas Search 也会包含不属于指定存储桶的分面运算符的结果,但 Atlas Search 不会将这些结果包含在任何存储桶计数中。 | no |
path | 字符串 | 用于分面的字段路径。您可将被索引字段指定为 dateFacet 类型。 | 是 |
type | 字符串 | 分面类型。值必须是 date 。 | 是 |
例子
例子
以下示例将对 sample_mflix.movies
集合使用名为 default
的索引。集合中的 released
字段被索引为 dateFacet 和 date 类型。
{ "mappings": { "dynamic": false, "fields": { "released": [ { "type": "dateFacet" }, { "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
存储桶,以便检索不属于任何指定边界的查询结果。
db.movies.aggregate([ { "$searchMeta": { "facet": { "operator": { "range": { "path": "released", "gte": ISODate("2000-01-01T00:00:00.000Z"), "lte": ISODate("2015-01-31T00:00:00.000Z") } }, "facets": { "yearFacet": { "type": "date", "path": "released", "boundaries": [ISODate("2000-01-01"), ISODate("2005-01-01"), ISODate("2010-01-01"), ISODate("2015-01-01")], "default": "other" } } } } } ])
此查询将返回以下结果:
[ { count: { lowerBound: Long('11922') }, facet: { yearFacet: { buckets: [ { _id: ISODate('2000-01-01T00:00:00.000Z'), count: Long('3028') }, { _id: ISODate('2005-01-01T00:00:00.000Z'), count: Long('3953') }, { _id: ISODate('2010-01-01T00:00:00.000Z'), count: Long('4832') }, { _id: 'other', count: Long('109') } ] } } } ]
要了解有关这些结果的更多信息,请参阅分面结果。
分面结果
对于分面查询,Atlas Search 返回定义的分面名称与结果中该分面的存储桶数组的映射。分面结果文档包含 buckets
选项,此选项是分面结果存储桶的数组。数组中的每个分面存储桶文档都包含以下字段:
选项 | 类型 | 说明 |
---|---|---|
_id | 对象 | 标识此方面存储桶的唯一标识符。此值与正在分面的数据类型相匹配。 |
count | int | 此分面存储桶中的文档计数。要了解有关 count 字段的详情,请参阅计算 Atlas Search 结果。 |
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
查询,以便检索搜索结果和元数据结果。
索引定义为要索引的字段指定了以下内容:
字段名称 | 数据类型 |
---|---|
directors | |
year | |
released |
{ "mappings": { "dynamic": false, "fields": { "directors": { "type": "stringFacet" }, "year": { "type": "numberFacet" }, "released": { "type": "date" } } } }
以下查询搜索 2000 年 1 月 1 日至 2015 年 1 月 31 日之间上映的电影。它请求 directors
和 year
字段的元数据。
db.movies.aggregate([ { "$searchMeta": { "facet": { "operator": { "range": { "path": "released", "gte": ISODate("2000-01-01T00:00:00.000Z"), "lte": ISODate("2015-01-31T00:00:00.000Z") } }, "facets": { "directorsFacet": { "type": "string", "path": "directors", "numBuckets" : 7 }, "yearFacet" : { "type" : "number", "path" : "year", "boundaries" : [2000,2005,2010, 2015] } } } } } ])
Atlas Search 返回以下结果:
[ { "count" : { "lowerBound" : NumberLong(13064) }, "facet" : { "yearFacet" : { "buckets" : [ { "_id" : 2000, "count" : NumberLong(3283) }, { "_id" : 2005, "count" : NumberLong(4365) }, { "_id" : 2010, "count" : NumberLong(5123) } ] }, "directorsFacet" : { "buckets" : [ { "_id" : "Takashi Miike", "count" : NumberLong(29) }, { "_id" : "Johnnie To", "count" : NumberLong(23) }, { "_id" : "Steven Soderbergh", "count" : NumberLong(21) }, { "_id" : "Michael Winterbottom", "count" : NumberLong(19) }, { "_id" : "Ken Loach", "count" : NumberLong(16) }, { "_id" : "Ki-duk Kim", "count" : NumberLong(16) }, { "_id" : "Ridley Scott", "count" : NumberLong(15) } ] } } } ]
结果显示 sample_mflix.movies
集合中的以下计数:
Atlas Search 为查询返回的从 2000 年(含下限)到 2015 年(不含上限)的电影数量
Atlas Search 为查询返回的每位导演的电影数量
索引定义为要索引的字段指定了以下内容:
字段名称 | 数据类型 |
---|---|
genres | |
released |
{ "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 必须返回与该查询匹配的文档。
db.movies.aggregate([ { "$search": { "facet": { "operator": { "near": { "path": "released", "origin": ISODate("1999-07-01T00:00:00.000+00:00"), "pivot": 7776000000 } }, "facets": { "genresFacet": { "type": "string", "path": "genres" } } } } }, { "$limit": 2 }, { "$facet": { "docs": [ { "$project": { "title": 1, "released": 1 } } ], "meta": [ {"$replaceWith": "$$SEARCH_META"}, {"$limit": 1} ] } }, { "$set": { "meta": { "$arrayElemAt": ["$meta", 0] } } } ])
查询返回以下结果:
[ { docs: [ { _id: ObjectId("573a1393f29313caabcde1ae"), title: 'Begone Dull Care', released: ISODate("1999-07-01T00:00:00.000Z") }, { _id: ObjectId("573a13a9f29313caabd2048a"), title: 'Fara', released: ISODate("1999-07-01T00:00:00.000Z") } ], meta: { count: { lowerBound: Long("20878") }, facet: { genresFacet: { buckets: [ { _id: 'Drama', count: Long('12149') }, { _id: 'Comedy', count: Long('6436') }, { _id: 'Romance', count: Long('3274') }, { _id: 'Crime', count: Long('2429') }, { _id: 'Thriller', count: Long('2400') }, { _id: 'Action', count: Long('2349') }, { _id: 'Adventure', count: Long('1876') }, { _id: 'Documentary', count: Long('1755') }, { _id: 'Horror', count: Long('1432') }, { _id: 'Biography', count: Long('1244') } ] } } } } ]
要了解有关这些结果的更多信息,请参阅分面结果。