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

facet

在此页面上

  • 兼容性
  • 定义
  • 语法
  • 字段
  • 分面定义
  • 字符串分面
  • 数值分面
  • 日期分面
  • 分面结果
  • SEARCH_META 聚合变量
  • 限制
  • 示例

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>
}
}
}
}
字段
类型
必需?
说明
facets
文档
用于对每个分面的数据进行分桶的信息。您必须指定至少一个分面定义
operator
文档
no
用于执行分面操作的操作符。如省略,Atlas Search 将对集合中的所有文档执行分面操作。

分面定义文档包含分面名称和特定于分面类型的选项。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 类型的值的任意组合:

  • 32 位整数 (int32)

  • 64 位整数 (int64)

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

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 字段中搜索 19802000 年间的影片,并检索查询的元数据结果。此查询指定了三个存储桶:

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

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

  • 20001990存储桶的独占上限

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

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 字段被索引为 dateFacetdate 类型。

{
"mappings": {
"dynamic": false,
"fields": {
"released": [
{
"type": "dateFacet"
},
{
"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 存储桶,以便检索不属于任何指定边界的查询结果。

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

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

适用以下限制:

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

  • 只能在运行 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 日之间上映的电影。它请求 directorsyear 字段的元数据。

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 输出字段中排除文件中除titlereleased 字段以外的所有字段

  • $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') }
]
}
}
}
}
]

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

后退

存在