Definition
facetThe
facetcollector groups results by values or ranges in the specified faceted fields and returns the count for each of those groups.You can use
facetwith both the$searchand$searchMetastages. MongoDB recommends usingfacetwith the$searchMetastage to retrieve metadata results only for the query. To retrieve metadata results and query results using the$searchstage, you must use the$$SEARCH_METAaggregation variable. SeeSEARCH_METAAggregation Variable to learn more.
Syntax
facet has the following syntax:
{ "$searchMeta"|"$search": { "index": <index name>, // optional, defaults to "default" "facet": { "operator": { <operator-specifications> }, "facets": { <facet-definitions> } } } }
Fields
Field | Type | Required? | Description |
|---|---|---|---|
| document | yes | Information for bucketing the data for each facet. You must specify at least one Facet Definition. |
| document | no | Operator to use to perform the facet over. If omitted, MongoDB Search performs the facet over all documents in the collection. |
Facet Definition
The facet definition document contains the facet name and options specific to a type of facet. MongoDB Search supports the following types of facets:
String Facets
Important
stringFacet is now deprecated. Use token instead.
String facets allow you to narrow down MongoDB Search results based on the most frequent string values in the specified string field. Note that the string field must be indexed as token. To facet on string fields in embedded documents, you must also index the parent fields as the document type. When you facet on strings in arrays or embedded documents, MongoDB Search returns facet counts based on the number of matching root documents.
Syntax
String facets have the following syntax:
{ "$searchMeta": { "facet":{ "operator": { <operator-specification> }, "facets": { "<facet-name>" : { "type" : "string", "path" : "<field-path>", "numBuckets" : <number-of-categories>, } } } } }
Options
Option | Type | Description | Required? |
|---|---|---|---|
| int | Maximum number of facet categories to return in the results.
Value must be less than or equal to | no |
| string | Field path to facet on. You can specify a field that is indexed as a token. | yes |
| string | Type of facet. Value must be | yes |
Example
Example
The following example uses an index named default on the
sample_mflix.movies collection. The genres field in the
collection is indexed as the token type and the year field is
indexed as the number type.
{ "mappings": { "dynamic": false, "fields": { "genres": { "type": "token" }, "year": { "type": "number" } } } }
The query uses the $searchMeta stage to search the
year field in the movies collection for movies from 2000 to
2015 and retrieve a count of the number of movies in each genre.
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 ]
To learn more about these results, see Facet Results.
Numeric Facets
Important
numberFacet is now deprecated. Use number instead.
Numeric facets allow you to determine the frequency of numeric values in your search results by breaking the results into separate ranges of numbers. When you facet on numbers in arrays or embedded documents, MongoDB Search returns facet counts based on the number of matching root documents.
Syntax
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>" } } } } }
Options
Option | Type | Description | Required? |
|---|---|---|---|
| array of numbers | List of numeric values, in ascending order, that specify the
boundaries for each bucket. You must specify at least two
boundaries, which are less than or equal to one thousand (
| yes |
| string | Name of an additional bucket that counts documents returned from the operator that do not fall within the specified boundaries. If omitted, MongoDB 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 |
| string | Field path to facet on. You can specify a field that is indexed as the number type. | yes |
| string | Type of facet. Value must be | yes |
Example
Example
The following example uses an index named default on the
sample_mflix.movies collection. The year field in the
collection is indexed as the number type.
{ "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 bucket1990, exclusive upper bound for the1980bucket and inclusive lower bound for this bucket2000, exclusive upper bound for the1990bucket
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.
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 ]
To learn more about these results, see Facet Results.
Date Facets
Date facets allow you to narrow down search results based on a date. When you facet on dates in arrays or embedded documents, MongoDB Search returns facet counts based on the number of matching root documents.
Syntax
Date facets have the following syntax:
{ "$searchMeta": { "facet":{ "operator": { <operator-specification> }, "facets": { "<facet-name>" : { "type" : "date", "path" : "<field-path>", "boundaries" : <array-of-dates>, "default": "<bucket-name>" } } } } }
Options
Option | Type | Description | Required? |
|---|---|---|---|
| array of numbers | List of date values that specify the boundaries for each bucket. You must specify:
Each adjacent pair of values acts as the inclusive lower bound and the exclusive upper bound for the bucket. | yes |
| string | Name of an additional bucket that counts documents returned from the operator that do not fall within the specified boundaries. If omitted, MongoDB Search includes the results of the facet operator that do not fall under a specified bucket also, but MongoDB Search doesn't include these results in any bucket counts. | no |
| string | Field path to facet on. You can specify a field that is indexed as a date type. | yes |
| string | Type of facet. Value must be | yes |
Example
Example
The following example uses an index named default on the
sample_mflix.movies collection. The released field in the
collection is indexed as the date
type.
{ "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 bucket2005-01-01, exclusive upper bound for the2000-01-01bucket and inclusive lower bound for this bucket2010-01-01, exclusive upper bound for the2005-01-01bucket and inclusive lower bound for this bucket2015-01-01, exclusive upper bound for the2010-01-01bucket
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.
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 ]
To learn more about these results, see Facet Results.
Facet Results
For a facet query, MongoDB 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 |
|---|---|---|
| object | Unique identifier that identifies this facet bucket. This value matches the type of data that is being faceted on. |
| int | Count of documents in this facet bucket. To learn more about the
|
SEARCH_META Aggregation Variable
When you run your query using the $search stage, MongoDB 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.
MongoDB recommends using the $$SEARCH_META variable only if you
need both the search results and the metadata results. Otherwise, use
the:
$searchstage for just the search results.$searchMetastage for just the metadata results.
Limitations
The following limitations apply:
You can run facet queries on a single field only. You can't run facet queries on groups of fields.
You can't run facet queries over sharded collections on clusters.
Examples
The following examples use the sample_mflix.movies collection. The
metadata results example demonstrates how to run a
$searchMeta query with facet to retrieve only the
metadata in the results. The metadata and search results example
demonstrates how to run a $search query with facet and
the $SEARCH_META aggregation variable to retrieve both the search
and metadata results.
The index definition specifies the following for the fields to index:
{ "mappings": { "dynamic": false, "fields": { "directors": { "type": "token" }, "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.
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 ]
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 MongoDB Search returned for the query
Number of movies for each director that MongoDB Search returned for the query
The index definition specifies the following for the fields to index:
{ "mappings": { "dynamic": false, "fields": { "genres": { "type": "token" }, "released": { "type": "date" } } } }
The following query searches for movies released near July 01,
1999 using the $search stage. The query includes a
$facet stage to process the input documents using
the following sub-pipeline stages:
$projectstage to exclude all fields in the documents except thetitleandreleasedfields in thedocsoutput field$limitstage to do the following:Limit the
$searchstage output to2documentsLimit the output to
1document in themetaoutput field
Note
The limit must be small for the results to fit in a 16 MB document.
$replaceWithstage to include the metadata results stored in the$$SEARCH_METAvariable in themetaoutput field
The query also includes a $set stage to add the
meta field.
Note
To see the metadata results for the following query, MongoDB Search must return documents that match the query.
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 ]
To learn more about these results, see Facet Results.
Continue Learning
To learn more, see How to Use Facets with MongoDB Search.
You can learn more about facet (MongoDB Search Operator) in MongoDB Search with our
course and video.
Learn with Courses
To learn more about using facets in MongoDB Search, take Unit 9 of the
Intro To MongoDB Course on MongoDB University. The 1.5 hour unit includes an overview
of MongoDB Search and lessons on creating MongoDB Search indexes, running
$search queries using compound operators,
and grouping results using facet.
Learn by Watching
Follow along with this video to learn about how you can create and use a
numeric and string facet (MongoDB Search Operator) in your query to group results
and retrieve a count of the results in the groups.
Duration: 11 Minutes