Docs Menu

facet

On this page

  • Definition
  • Syntax
  • Fields
  • Facet Definition
  • Facet Results
  • SEARCH_META Aggregation Variable
  • Examples
Important

facet is only available on Atlas clusters running MongoDB v4.4 or higher.

facet

The facet collector groups results by values or ranges in the specified faceted fields and returns the count for each of those groups.

You can use facet with both the $search and $searchMeta stages. MongoDB recommends using facet with the $searchMeta stage to retrieve metadata results only for the query. To retrieve metadata results and query results using the $search stage, you must use the $$SEARCH_META aggregation variable. See SEARCH_META Aggregation Variable to learn more.

facet has the following syntax:

{
"$searchMeta"|"$search": {
"index": <index name>, // optional, defaults to "default"
"facet": {
"operator": {
<operator-specifications>
},
"facets": {
<facet-definitions>
}
}
}
}
Field
Type
Required?
Description
facets
document
yes
Information for bucketing the data for each facet. You must specify at least one Facet Definition.
operator
document
yes
Operator to use to perform the facet over.

The facet definition document contains the facet name and options specific to a type of facet. Atlas Search supports the following types of facets:

String facets allow you to narrow down Atlas Search results based on the most frequent string values in the specified string field. Note that the string field must be indexed as stringFacet.

String facets have the following syntax:

{
"$searchMeta": {
"facet":{
"operator": {
<operator-specification>
},
"facets": {
"<facet-name>" : {
"type" : "string",
"path" : "<field-path>",
"numBuckets" : <number-of-categories>,
}
}
}
}
}
Option
Type
Description
Required?
numBuckets
int
Maximum number of facet categories to return in the results. Value must be less than or equal to 1000. If specified, Atlas Search may return fewer categories than requested if the data is grouped into fewer categories than your requested number. If omitted, defaults to 10, which means that Atlas Search will return only the top 10 facet categories by count.
no
path
string
Field path to facet on. You can specify a field that is indexed as a stringFacet.
yes
type
string
Type of facet. Value must be string.
yes
Example

The following example uses an index named default on the sample_mflix.movies collection. The title field in the collection is indexed as type stringFacet and string so that both the text and the facet search return correct results.

{
"mappings": {
"dynamic": false,
"fields": {
"title": [
{
"type": "stringFacet"
},
{
"type": "string"
}
]
}
}
}

The query uses the $searchMeta stage to search the title field in the movies collection for the term new and retrieve metadata results for the query string. The query requests only the top 7 facet categories by count.

db.movies.aggregate([
{
"$searchMeta": {
"facet": {
"operator": {
"text": {
"path": "title",
"query": "new"
}
},
"facets": {
"titleFacet": {
"type": "string",
"path": "title",
"numBuckets" : 7
}
}
}
}
}
])

This query returns the following results:

{
"count" : {
"lowerBound" : NumberLong(101)
},
"facet" : {
"titleFacet" : {
"buckets" : [
{ "_id" : "The New Land", "count" : Long(5) },
{ "_id" : "Aftershock: Earthquake in New York", "count" : Long(2) },
{ "_id" : "Happy New Year", "count" : Long(2) },
{ "_id" : "Scanners II: The New Order", "count" : Long(2) },
{ "_id" : "The New Adventures of Pippi Longstocking", "count" : Long(2) },
{ "_id" : "2 Days in New York", "count" : Long(1) },
{ "_id" : "A Brand New Life", "count" : Long(1) }
]
}
}
}

To learn more about these results, see Facet Results.

Numeric facets allow you to determine the frequency of numeric values in your search results by breaking the results into separate ranges of numbers.

Numeric facets have the following syntax:

{
"$searchMeta": {
"facet":{
"operator": {
<operator-specification>
},
"facets": {
"<facet-name>" : {
"type" : "number",
"path" : "<field-path>",
"boundaries" : <array-of-numbers>,
"default": "<bucket-name>"
}
}
}
}
}
Option
Type
Description
Required?
boundaries
array of numbers

List of numeric values, in ascending order, that specify the boundaries for each bucket. You must specify at least two boundaries. Each adjacent pair of values acts as the inclusive lower bound and the exclusive upper bound for the bucket. You can specify any combination of values of the following BSON types:

  • 32-bit integer (int32)
  • 64-bit integer (int64)
  • 64-bit binary floating point (double)
yes
default
string
Name of an additional bucket that counts documents returned from the operator that do not fall within the specified boundaries. If omitted, Atlas Search includes the results of the facet operator that do not fall under a specified bucket also, but doesn't include it in any bucket counts.
no
path
string
Field path to facet on. You can specify a field that is indexed as a number.
yes
type
string
Type of facet. Value must be number.
yes
Example

The following example uses an index named default on the sample_mflix.movies collection. The year field in the collection is indexed as type number.

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

The query uses the $searchMeta stage to search the year field in the movies collection for movies between the years 1980 to 2000 and retrieve metadata results for the query. The query specifies three buckets:

  • 1980, inclusive lower bound for this bucket
  • 1990, exclusive upper bound for the 1980 bucket and inclusive lower bound for this bucket
  • 2000, exclusive upper bound for the 1990 bucket

The query also specifies a default bucket named other to retrieve results of the query that don't fall under any of the specified boundaries.

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"
}
}
}
}
}
])

This query returns the following results:

{
"count" : {
"lowerBound" : NumberLong(6472)
},
"facet" : {
"yearFacet" : {
"buckets" : [
{ "_id" : 1980, "count" : NumberLong(2081) },
{ "_id" : 1990, "count" : NumberLong(3773) },
{ "_id" : "other", "count" : NumberLong(618) }
]
}
}
}

To learn more about these results, see Facet Results.

Date facets allow you to narrow down search results based on a date.

Date facets have the following syntax:

{
"$searchMeta": {
"facet":{
"operator": {
<operator-specification>
},
"facets": {
"<facet-name>" : {
"type" : "number",
"path" : "<field-path>",
"boundaries" : <array-of-numbers>,
"default": "<bucket-name>"
}
}
}
}
}
Option
Type
Description
Required?
boundaries
array of numbers

List of date values that specify the boundaries for each bucket. You must specify:

  • At least two boundaries
  • Values in ascending order, with the earliest date first

Each adjacent pair of values acts as the inclusive lower bound and the exclusive upper bound for the bucket.

yes
default
string
Name of an additional bucket that counts documents returned from the operator that do not fall within the specified boundaries. If omitted, Atlas Search includes the results of the facet operator that do not fall under a specified bucket also, but Atlas Search doesn't include these results in any bucket counts.
no
path
string
Field path to facet on. You can specify a field that is indexed as a date.
yes
type
string
Type of facet. Value must be date.
yes
Example

The following example uses an index named default on the sample_mflix.movies collection. The released field in the collection is indexed as type date.

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

The query uses the $searchMeta stage to search the released field in the movies collection for movies between the years 2000 to 2015 and retrieve metadata results for the query string. The query specifies four buckets:

  • 2000-01-01, inclusive lower bound for this bucket
  • 2005-01-01, exclusive upper bound for the 2000-01-01 bucket and inclusive lower bound for this bucket
  • 2010-01-01, exclusive upper bound for the 2005-01-01 bucket and inclusive lower bound for this bucket
  • 2015-01-01, exclusive upper bound for the 2010-01-01 bucket

The query also specifies a default bucket named other to retrieve results of the query that don't fall under any of the specified boundaries.

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"
}
}
}
}
}
])

This query returns the following results:

{
"count" : {
"lowerBound" : NumberLong(13064)
},
"facet" : {
"releaseFacet" : {
"buckets" : [
{
"_id" : ISODate("2000-01-01T00:00:00Z"),
"count" : NumberLong(3242)
},
{
"_id" : ISODate("2005-01-01T00:00:00Z"),
"count" : NumberLong(4266)
},
{
"_id" : ISODate("2010-01-01T00:00:00Z"),
"count" : NumberLong(5445)
},
{
"_id" : "other",
"count" : NumberLong(111)
}
]
}
}
}

To learn more about these results, see Facet Results.

For a facet query, Atlas Search returns a mapping of the defined facet names to an array of buckets for that facet in the results. The facet result document contains the buckets option, which is an array of resulting buckets for the facet. Each facet bucket document in the array has the following fields:

Option
Type
Description
_id
object
Unique identifier that identifies this facet bucket. This value matches the type of data that is being faceted on.
count
int
Count of documents in this facet bucket. To learn more about the count field, see Counting.

When you run your query using the $search stage, Atlas Search stores the metadata results in the $$SEARCH_META variable and returns only the search results. You can use the $$SEARCH_META variable in all the supported aggregation pipeline stages to view the metadata results for your $search query.

Note

You can't use the $$SEARCH_META variable to retrieve metadata results for queries over sharded collections.

MongoDB recommends using the $$SEARCH_META variable only if you need both the search results and the metadata results. Otherwise, use the:

  • $search stage for just the search results.
  • $searchMeta stage for just the metadata results.
Example

Suppose the following index on the sample_mflix.movies collection.

{
"mappings": {
"dynamic": false,
"analyzer": "lucene.standard",
"fields": {
"genres": {
"type": "stringFacet"
},
"released": {
"type": "date"
}
}
}
}

The following query searches for movies released near July 01, 1999 using the $search stage. It requests a count of the number of movies in each genre. The query also includes a:

  • $project stage to exclude all fields in the documents except the title and released fields and include the metadata results stored in the $$SEARCH_META variable as the value of a field named newField
  • $limit stage to limit the output to 2 documents.
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"
}
}
}
}
},
{
$project: {
"newField": "$$SEARCH_META",
"title": 1,
"released": 1
}
},
{
"$limit": 2
}
])

The query returns the following results:

{
"_id" : ObjectId("573a1393f29313caabcde1ae"),
"title" : "Begone Dull Care",
"released" : ISODate("1999-07-01T00:00:00Z"),
"newField" : {
"count" : { "lowerBound" : NumberLong(23026) },
"facet" : {
"genresFacet" : {
"buckets" : [
{ "_id" : "Drama", "count" : NumberLong(13527) },
{ "_id" : "Comedy", "count" : NumberLong(6922) },
{ "_id" : "Romance", "count" : NumberLong(3615) },
{ "_id" : "Crime", "count" : NumberLong(2649) },
{ "_id" : "Thriller", "count" : NumberLong(2603) },
{ "_id" : "Action", "count" : NumberLong(2505) },
{ "_id" : "Documentary", "count" : NumberLong(2041) },
{ "_id" : "Adventure", "count" : NumberLong(2016) },
{ "_id" : "Horror", "count" : NumberLong(1662) },
{ "_id" : "Biography", "count" : NumberLong(1373) }
]
}
}
}
}
{
"_id" : ObjectId("573a13a9f29313caabd2048a"),
"title" : "Fara",
"released" : ISODate("1999-07-01T00:00:00Z"),
"newField" : {
"count" : { "lowerBound" : NumberLong(23026) },
"facet" : {
"genresFacet" : {
"buckets" : [
{ "_id" : "Drama", "count" : NumberLong(13527) },
{ "_id" : "Comedy", "count" : NumberLong(6922) },
{ "_id" : "Romance", "count" : NumberLong(3615) },
{ "_id" : "Crime", "count" : NumberLong(2649) },
{ "_id" : "Thriller", "count" : NumberLong(2603) },
{ "_id" : "Action", "count" : NumberLong(2505) },
{ "_id" : "Documentary", "count" : NumberLong(2041) },
{ "_id" : "Adventure", "count" : NumberLong(2016) },
{ "_id" : "Horror", "count" : NumberLong(1662) },
{ "_id" : "Biography", "count" : NumberLong(1373) }
]
}
}
}
}

To learn more about these results, see Facet Results.

This example uses the following index definition on the sample_mflix.movies collection. The index definition specifies the following for the fields to index:

Field Name
Data Type
genres
year
released
{
"mappings": {
"dynamic": false,
"fields": {
"directors": {
"type": "stringFacet"
},
"year": {
"type": "number"
},
"released": {
"type": "date"
}
}
}
}

The following query searches for movies released between January 01, 2000 and January 31, 2015. It requests metadata on the directors and year field.

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 returns the following results:

{
"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) } ]
}
}
}

The results show a count of the following in the sample_mflix.movies collection:

  • Number of movies from the year 2000, inclusive lower bound, to 2015, exclusive upper bound, that Atlas Search returned for the query
  • Number of movies for each director that Atlas Search returned for the query
Give Feedback
© 2021 MongoDB, Inc.

About

  • Careers
  • Legal Notices
  • Privacy Notices
  • Security Information
  • Trust Center
© 2021 MongoDB, Inc.