Docs Menu

How to Use Facets with Atlas Search

This tutorial describes how to create an index with a facet definition on string, date, and numeric fields in the sample_mflix.movies collection. It shows how to run an Atlas Search query against those fields for results grouped by values for the string field and by ranges for the date and numeric fields, including the count for each of those groups. It takes you through the following steps:

  1. Set up an Atlas Search index with facet definition on the genres, released, and year fields in the sample_mflix.movies collection.

  2. Run Atlas Search query against the released field in the sample_mflix.movies collection for results grouped by values for the genres field and by ranges for the year field.

To create an Atlas Search index, you must have Project Data Access Admin or higher access to the project.

To complete these tutorials, in addition to the prerequisites listed in the Atlas Search Tutorials page, you must have an Atlas cluster running one of the following versions:

  • MongoDB 5.0.4+

  • MongoDB 6.0+

  • MongoDB 7.0+

In this section, you will create an Atlas Search index on the genres, year, and released fields in the sample_mflix.movies collection.

1
  1. If it's not already displayed, select the organization that contains your desired project from the Organizations menu in the navigation bar.

  2. If it's not already displayed, select your desired project from the Projects menu in the navigation bar.

  3. If it's not already displayed, click Clusters in the sidebar.

    The Clusters page displays.

2

You can go the Atlas Search page from the sidebar, the Data Explorer, or your cluster details page.

  1. In the sidebar, click Atlas Search under the Services heading.

    Note

    If you have no clusters, click Create cluster to create one. To learn more, see Create a Cluster.

  2. From the Select data source dropdown, select your cluster and click Go to Atlas Search.

    The Atlas Search page displays.

  1. Click the Browse Collections button for your cluster.

  2. Expand the database and select the collection.

  3. Click the Search Indexes tab for the collection.

    The Atlas Search page displays.

  1. Click the cluster's name.

  2. Click the Atlas Search tab.

    The Atlas Search page displays.

3
4

Make the following selections on the page and then click Next.

Search Type

Select the Atlas Search index type.

Index Name and Data Source

Specify the following information:

  • Index Name: facet-tutorial

  • Database and Collection:

    • sample_mflix database

    • movies collection

Configuration Method

For a guided experience, select Visual Editor.

To edit the raw index definition, select JSON Editor.
5

You can create an Atlas Search index that uses dynamic mappings or static mappings. To learn more about dynamic and static mappings, see Static and Dynamic Mappings.

The following index definition statically indexes the genres field as stringFacet type and dynamically indexes the other fields of supported types in each document in the movies collection. You can use the Atlas Search Visual Editor or the Atlas Search JSON Editor in the Atlas user interface to create the index.

  1. Click Next, then click Review Your Index.

  2. Click Add Field Mapping under Field Mappings section.

  3. Click Customzed COnfiguration and select the following from the dropdowns:

    Field Name

    genres

    Data Type

    StringFacet

  4. Click Add, then click Save Changes.

  1. Click Next.

  2. Review the index definition.

    Your index definition should look similar to the following:

    {
    "mappings": {
    "dynamic": true,
    "fields": {
    "genres": {
    "type": "stringFacet"
    }
    }
    }
    }
  3. Click Next.

6
7

A modal window appears to let you know your index is building. Click the Close button.

8

The index should take about one minute to build. While it is building, the Status column reads Build in Progress. When it is finished building, the Status column reads Active.


➤ Use the Select your language drop-down menu to set the language of the examples in this section.


You can use facet in queries that use the $search and $searchMeta stages. In this section, connect to your Atlas cluster and the run the sample query against the sample_mflix.movies collection using the $searchMeta or $search stage to group the genre and year fields into buckets. To optimize performance:

  • Use $searchMeta stage if you only need the facet metadata.

  • Use $search stage if you want to retrieve both the query results and the facet metadata.

1
  1. If it's not already displayed, select the organization that contains your desired project from the Organizations menu in the navigation bar.

  2. If it's not already displayed, select your desired project from the Projects menu in the navigation bar.

  3. If it's not already displayed, click Clusters in the sidebar.

    The Clusters page displays.

2

You can go the Atlas Search page from the sidebar, the Data Explorer, or your cluster details page.

  1. In the sidebar, click Atlas Search under the Services heading.

    Note

    If you have no clusters, click Create cluster to create one. To learn more, see Create a Cluster.

  2. From the Select data source dropdown, select your cluster and click Go to Atlas Search.

    The Atlas Search page displays.

  1. Click the Browse Collections button for your cluster.

  2. Expand the database and select the collection.

  3. Click the Search Indexes tab for the collection.

    The Atlas Search page displays.

  1. Click the cluster's name.

  2. Click the Atlas Search tab.

    The Atlas Search page displays.

3

Click the Query button to the right of the index to query.

4

Click Edit $search Query to view a default query syntax sample in JSON format.

5

To run the query, copy and paste the following query into the the Query Editor, then click Search.

The following query searches for movies released near November 11, 1921. It specifies a pivot distance from origin of approximately three months. It requests metadata on the genres and year field. The query requests a count of the:

  • Number of movies in each genre in the genres string array field

  • Number of movies in the years 1910 to 1939, inclusive

[
{
"$searchMeta": {
"index": "facet-tutorial",
"facet": {
"operator": {
"near": {
"path": "released",
"origin": ISODate("1921-11-01T00:00:00.000+00:00"),
"pivot": 7776000000
}
},
"facets": {
"genresFacet": {
"type": "string",
"path": "genres"
},
"yearFacet" : {
"type" : "number",
"path" : "year",
"boundaries" : [1910,1920,1930,1940]
}
}
}
}
}
]
6

The Search Tester might not display all the values for the fields in the results. To view all the values for the fields in the results, expand the fields.

Atlas Search displays the following results in the page:

count: Object
lowerBound: 20878
facet: Object
genresFacet: Object
buckets: Array (10)
0: Object
_id: "Drama"
count: 12149
1: Object
_id: "Comedy"
count: 6436
2: Object
_id: "Romance"
count: 3274
3: Object
_id: "Crime"
count: 2429
4: Object
_id: "Thriller"
count: 2400
5: Object
_id: "Action"
count: 2349
6: Object
_id: "Adventure"
count: 1876
7: Object
_id: "Documentary"
count: 1755
8: Object
_id: "Horror"
count: 1432
9: Object
_id: "Biography"
count: 1244
yearFacet: Object
buckets: Array (3)
0: Object
_id: 1910
count: 14
1: Object
_id: 1920
count: 47
2: Object
_id: 1930
count: 238
1

Open mongosh in a terminal window and connect to your cluster. For detailed instructions on connecting, see Connect via mongosh.

2

Run the following command at mongosh prompt:

use sample_mflix
3

The sample query uses the following to query the collection:

  • near to search for movies released with a pivot distance from origin of approximately three months from November 11, 1921

  • facets to request the number of movies in each genre in the genres string array field and the number of movies in the years 1910 to 1939, inclusive

You can run this query using $searchMeta or using $search with the SEARCH_META aggregation variable.

1db.movies.aggregate([
2 {
3 "$searchMeta": {
4 "index": "facet-tutorial",
5 "facet": {
6 "operator": {
7 "near": {
8 "path": "released",
9 "origin": ISODate("1921-11-01T00:00:00.000+00:00"),
10 "pivot": 7776000000
11 }
12 },
13 "facets": {
14 "genresFacet": {
15 "type": "string",
16 "path": "genres"
17 },
18 "yearFacet" : {
19 "type" : "number",
20 "path" : "year",
21 "boundaries" : [1910,1920,1930,1940]
22 }
23 }
24 }
25 }
26 }
27])
[
{
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') }
]
},
yearFacet: {
buckets: [
{ _id: 1910, count: Long('14') },
{ _id: 1920, count: Long('47') },
{ _id: 1930, count: Long('238') }
]
}
}
}
}
]
db.movies.aggregate([
{
"$search": {
"index": "facet-tutorial",
"facet": {
"operator": {
"near": {
"path": "released",
"origin": ISODate("1921-11-01T00:00:00.000+00:00"),
"pivot": 7776000000
}
},
"facets": {
"genresFacet": {
"type": "string",
"path": "genres"
},
"yearFacet": {
"type": "number",
"path": "year",
"boundaries" : [1910,1920,1930,1940]
}
}
}
}
},
{
"$facet": {
"meta": [
{"$replaceWith": "$$SEARCH_META"},
{"$limit": 1}
]
}
},
{
"$set": {
"meta": {
"$arrayElemAt": ["$meta", 0]
}
}
}
])
[
{
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') }
]
},
yearFacet: {
buckets: [
{ _id: 1910, count: Long('14') },
{ _id: 1920, count: Long('47') },
{ _id: 1930, count: Long('238') }
]
}
}
}
}
]
1

Open MongoDB Compass and connect to your cluster. For detailed instructions on connecting, see Connect via Compass.

2

On the Database screen, click the sample_mflix database, then click the movies collection.

3

The query uses the following searchMeta operator clauses:

  • near to search for movies released with a pivot distance from origin of approximately three months from November 11, 1921

  • facets to request the number of movies in each genre in the genres string array field and the number of movies in the years 1910 to 1939, inclusive

To run this query in MongoDB Compass:

  1. Click the Aggregations tab.

  2. Click Select..., then configure each of the following pipeline stages by selecting the stage from the dropdown and adding the query for that stage. Click Add Stage to add additional stages.

    You can run this query using $searchMeta or using $search with the SEARCH_META aggregation variable.

    Pipeline Stage
    Query

    $searchMeta

    {
    index: 'facet-tutorial',
    facet: {
    operator: {
    near: {
    path: 'released',
    origin: ISODate("1921-11-01T00:00:00.000+00:00"),
    pivot: 7776000000
    }
    },
    facets: {
    genresFacet: {
    type: 'string',
    path: 'genres'
    },
    yearFacet: {
    type: 'number',
    path: 'year',
    boundaries: [1910,1920,1930,1940]
    }
    }
    }
    }
    Pipeline Stage
    Query

    $search

    {
    "index": "facet-tutorial",
    "facet": {
    "operator": {
    "near": {
    "path": "released",
    "origin": ISODate("1921-11-01T00:00:00.000+00:00"),
    "pivot": 7776000000
    }
    },
    "facets": {
    "genresFacet": {
    "type": "string",
    "path": "genres"
    },
    "yearFacet": {
    "type": "number",
    "path": "year",
    "boundaries" : [1910,1920,1930,1940]
    }
    }
    }
    }

    $facet

    {
    meta: [
    {
    $replaceWith: "$$SEARCH_META"
    },
    {
    $limit: 1
    }
    ]
    }

    $set

    {
    meta: {
    $arrayElemAt: ["$meta", 0]
    }
    }

If you enabled Auto Preview, MongoDB Compass displays the following documents next to the $set pipeline stage:

count: Object
lowerBound: 20878
facet: Object
genresFacet: Object
buckets: Array (10)
0: Object
_id: "Drama"
count: 12149
1: Object
_id: "Comedy"
count: 6436
2: Object
_id: "Romance"
count: 3274
3: Object
_id: "Crime"
count: 2429
4: Object
_id: "Thriller"
count: 2400
5: Object
_id: "Action"
count: 2349
6: Object
_id: "Adventure"
count: 1876
7: Object
_id: "Documentary"
count: 1755
8: Object
_id: "Horror"
count: 1432
9: Object
_id: "Biography"
count: 1244
yearFacet: Object
buckets: Array (3)
0: Object
_id: 1910
count: 14
1: Object
_id: 1920
count: 47
2: Object
_id: 1930
count: 238
1
  1. Create a new directory called facet-query-example and initialize your project with the dotnet new command.

    mkdir facet-query-example
    cd facet-query-example
    dotnet new console
  2. Add the .NET/C# Driver to your project as a dependency.

    dotnet add package MongoDB.Driver
2
  1. Replace the contents of the Program.cs file with the following code.

    The sample query uses the following to query the collection:

    • near to search for movies released with a pivot distance from origin of approximately three months from November 11, 1921

    • facets to request the number of movies in each genre in the genres string array field and the number of movies in the years 1910 to 1939, inclusive

    You can run this query using $searchMeta or using $search with the SEARCH_META aggregation variable.

    1using MongoDB.Bson;
    2using MongoDB.Bson.Serialization.Attributes;
    3using MongoDB.Bson.Serialization.Conventions;
    4using MongoDB.Driver;
    5using MongoDB.Driver.Search;
    6
    7public class FacetExample
    8{
    9 private const string MongoConnectionString = "<connection-string>";
    10
    11 public static void Main(string[] args)
    12 {
    13 // allow automapping of the camelCase database fields to our MovieDocument
    14 var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
    15 ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);
    16
    17 // connect to your Atlas cluster
    18 var mongoClient = new MongoClient(MongoConnectionString);
    19 var mflixDatabase = mongoClient.GetDatabase("sample_mflix");
    20 var moviesCollection = mflixDatabase.GetCollection<MovieDocument>("movies");
    21
    22 // declare data for date and number fields
    23 var originDate = new DateTime(1921, 11, 01, 0, 0, 0, DateTimeKind.Utc);
    24
    25 // define and run pipeline
    26 var results = moviesCollection.Aggregate()
    27 .SearchMeta(Builders<MovieDocument>.Search.Facet(
    28 Builders<MovieDocument>.Search.Near(movie => movie.Released, originDate, 7776000000),
    29 Builders<MovieDocument>.SearchFacet.String("genresFacet", movie => movie.Genres, 10),
    30 Builders<MovieDocument>.SearchFacet.Number("yearFacet", movie => movie.Year, 1910, 1920, 1930, 1940)),
    31 indexName: "facet-tutorial")
    32 .Single();
    33
    34 // print results
    35 Console.WriteLine(results.ToJson());
    36 }
    37}
    38
    39[BsonIgnoreExtraElements]
    40public class MovieDocument
    41{
    42 [BsonIgnoreIfDefault]
    43 public ObjectId Id { get; set; }
    44 public string [] Genres { get; set; }
    45 public DateTime Released { get; set; }
    46 public int Year { get; set; }
    47}
    1using MongoDB.Bson;
    2using MongoDB.Bson.Serialization.Attributes;
    3using MongoDB.Bson.Serialization.Conventions;
    4using MongoDB.Driver;
    5using MongoDB.Driver.Search;
    6using System;
    7
    8public class FacetExample
    9{
    10 private const string MongoConnectionString = "<your-connection-string>";
    11
    12 public static void Main(string[] args)
    13 {
    14 // Register camelCase conventions for document mapping
    15 var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
    16 ConventionRegistry.Register("CamelCase", camelCaseConvention, t => true);
    17
    18 // Connect to your MongoDB Atlas cluster
    19 var mongoClient = new MongoClient(MongoConnectionString);
    20 var mflixDatabase = mongoClient.GetDatabase("sample_mflix");
    21 var moviesCollection = mflixDatabase.GetCollection<MovieDocument>("movies");
    22
    23 // Define the origin date for the `near` operator
    24 var originDate = new DateTime(1921, 11, 01, 0, 0, 0, DateTimeKind.Utc);
    25
    26 // Create an array of BsonValues for the number boundaries
    27 var yearBoundaries = new BsonArray { 1910, 1920, 1930, 1940 };
    28
    29 // Define the $search stage
    30 var searchStage = Builders<MovieDocument>.Search.Facet(
    31 Builders<MovieDocument>.Search.Near(
    32 "released", // The field to search
    33 origin: originDate, // Starting date
    34 pivot: 7776000000 // Pivot (milliseconds)
    35 ),
    36 Builders<MovieDocument>.SearchFacet.String(
    37 "genresFacet", // Name of the string facet
    38 "genres" // The field to facet on
    39 ),
    40 Builders<MovieDocument>.SearchFacet.Number(
    41 "yearFacet", // Name of the number facet
    42 "year", // The field to facet on
    43 yearBoundaries
    44 )
    45 );
    46
    47 // Step 2: Aggregate pipeline implementationdd
    48 var pipeline = moviesCollection.Aggregate()
    49 .Search(searchStage, indexName: "facet-tutorial")
    50 .AppendStage<BsonDocument>(new BsonDocument
    51 {
    52 { "$facet", new BsonDocument
    53 {
    54 { "meta", new BsonArray
    55 {
    56 new BsonDocument { { "$replaceWith", "$$SEARCH_META" } },
    57 new BsonDocument { { "$limit", 1 } }
    58 }
    59 }
    60 }
    61 }
    62 })
    63 .AppendStage<BsonDocument>(new BsonDocument
    64 {
    65 { "$set", new BsonDocument
    66 {
    67 { "meta", new BsonDocument
    68 {
    69 { "$arrayElemAt", new BsonArray { "$meta", 0 } }
    70 }
    71 }
    72 }
    73 }
    74 })
    75 .ToList();
    76
    77 // Step 3: Output results
    78 foreach (var result in pipeline)
    79 {
    80 Console.WriteLine(result.ToJson());
    81 }
    82 }
    83}
    84
    85[BsonIgnoreExtraElements]
    86public class MovieDocument
    87{
    88 [BsonIgnoreIfDefault]
    89 public ObjectId Id { get; set; }
    90 public string[] Genres { get; set; }
    91 public DateTime Released { get; set; }
    92 public int Year { get; set; }
    93}
  2. Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

3
dotnet run facet-query-example.csproj
{
"meta" : {
"count" : { "lowerBound" : 20878 },
"facet" : {
"genresFacet" : {
"buckets" : [
{ "_id" : "Drama", "count" : 12149 },
{ "_id" : "Comedy", "count" : 6436 },
{ "_id" : "Romance", "count" : 3274 },
{ "_id" : "Crime", "count" : 2429 },
{ "_id" : "Thriller", "count" : 2400 },
{ "_id" : "Action", "count" : 2349 },
{ "_id" : "Adventure", "count" : 1876 },
{ "_id" : "Documentary", "count" : 1755 },
{ "_id" : "Horror", "count" : 1432 },
{ "_id" : "Biography", "count" : 1244 }
]
},
"yearFacet" : {
"buckets" : [
{ "_id" : 1910, "count" : 14 },
{ "_id" : 1920, "count" : 47 },
{ "_id" : 1930, "count" : 238 }
]
}
}
}
}
1
  1. Create a file named facet-query.go.

  2. Copy and paste the following code into the facet-query.go file.

    The code example performs the following tasks:

    • Imports mongodb packages and dependencies.

    • Establishes a connection to your Atlas cluster.

    • Uses the following searchMeta clauses to query the collection:

      • near to search for movies released with a pivot distance from origin of approximately three months from November 11, 1921

      • facets to request the number of movies in each genre in the genres string array field and the number of movies in the years 1910 to 1939, inclusive

    • Iterates over the cursor to print the documents that match the query.

    You can run this query using $searchMeta or using $search with the SEARCH_META aggregation variable.

    1package main
    2
    3import (
    4 "context"
    5 "fmt"
    6 "time"
    7
    8 "go.mongodb.org/mongo-driver/bson"
    9 "go.mongodb.org/mongo-driver/mongo"
    10 "go.mongodb.org/mongo-driver/mongo/options"
    11)
    12
    13func main() {
    14 // connect to your Atlas cluster
    15 client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI("<connection-string>"))
    16 if err != nil {
    17 panic(err)
    18 }
    19 defer client.Disconnect(context.TODO())
    20
    21 // set namespace
    22 collection := client.Database("sample_mflix").Collection("movies")
    23
    24 // define pipeline stages
    25 searchStage := bson.D{{"$searchMeta", bson.M{
    26 "index": "facet-tutorial",
    27 "facet": bson.M{
    28 "operator": bson.M{
    29 "near": bson.M{
    30 "path": "released",
    31 "origin": time.Date(1921, time.November, 1, 0, 0, 0, 0, time.UTC),
    32 "pivot": 7776000000},
    33 },
    34 "facets": bson.M{
    35 "genresFacet": bson.M{
    36 "path": "genres",
    37 "type": "string"},
    38 "yearFacet": bson.M{
    39 "path": "year",
    40 "type": "number",
    41 "boundaries": bson.A{1910, 1920, 1930, 1940}},
    42 }}}}}
    43 // run pipeline
    44 cursor, err := collection.Aggregate(context.TODO(), mongo.Pipeline{searchStage})
    45 if err != nil {
    46 panic(err)
    47 }
    48
    49 // print results
    50 var results []bson.D
    51 if err = cursor.All(context.TODO(), &results); err != nil {
    52 panic(err)
    53 }
    54 for _, result := range results {
    55 fmt.Println(result)
    56 }
    57}
    1package main
    2
    3import (
    4 "context"
    5 "fmt"
    6 "time"
    7
    8 "go.mongodb.org/mongo-driver/bson"
    9 "go.mongodb.org/mongo-driver/mongo"
    10 "go.mongodb.org/mongo-driver/mongo/options"
    11)
    12
    13func main() {
    14 // connect to your Atlas cluster
    15 client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI("<connection-string>"))
    16 if err != nil {
    17 panic(err)
    18 }
    19 defer client.Disconnect(context.TODO())
    20
    21 // set namespace
    22 collection := client.Database("sample_mflix").Collection("movies")
    23
    24 // define pipeline stages
    25 searchStage := bson.D{{"$search", bson.M{
    26 "index": "facet-tutorial",
    27 "facet": bson.M{
    28 "operator": bson.M{
    29 "near": bson.M{
    30 "path": "released",
    31 "origin": time.Date(1921, time.November, 1, 0, 0, 0, 0, time.UTC),
    32 "pivot": 7776000000},
    33 },
    34 "facets": bson.M{
    35 "genresFacet": bson.M{
    36 "path": "genres",
    37 "type": "string"},
    38 "yearFacet": bson.M{
    39 "path": "year",
    40 "type": "number",
    41 "boundaries": bson.A{1910, 1920, 1930, 1940}},
    42 },
    43 },
    44 }}}
    45
    46 facetStage:= bson.D{{"$facet", bson.D{
    47 {"meta", bson.A{
    48 bson.D{{"$replaceWith", "$$SEARCH_META"}},
    49 bson.D{{"$limit", 1}},
    50 }},
    51 }}}
    52 setStage:= bson.D{{"$set", bson.D{
    53 {"meta", bson.D{
    54 {"$arrayElemAt", bson.A{"$meta", 0}},
    55 }},
    56 }}}
    57
    58 // run pipeline
    59 cursor, err := collection.Aggregate(context.TODO(), mongo.Pipeline{searchStage, facetStage, setStage})
    60 if err != nil {
    61 panic(err)
    62 }
    63
    64 // print results
    65 var results []bson.D
    66 if err = cursor.All(context.TODO(), &results); err != nil {
    67 panic(err)
    68 }
    69 for _, result := range results {
    70 fmt.Println(result)
    71 }
    72}
  3. Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

  4. Run the following command to query your collection:

    go run facet-query.go
    [
    {count [
    {lowerBound 20878}
    ]}
    {facet [
    {genresFacet [
    {buckets [
    [{_id Drama} {count 12149}]
    [{_id Comedy} {count 6436}]
    [{_id Romance} {count 3274}]
    [{_id Crime} {count 2429}]
    [{_id Thriller} {count 2400}]
    [{_id Action} {count 2349}]
    [{_id Adventure} {count 1876}]
    [{_id Documentary} {count 1755}]
    [{_id Horror} {count 1432}]
    [{_id Biography} {count 1244}]
    ]}
    ]}
    {yearFacet [
    {buckets [
    [{_id 1910} {count 14}]
    [{_id 1920} {count 47}]
    [{_id 1930} {count 238}]
    ]}
    ]}
    ]}
    ]
1

junit

4.11 or higher version

mongodb-driver-sync

4.3.0 or higher version

slf4j-log4j12

1.7.30 or higher version

2
  1. Create a file named FacetQuery.java.

  2. Copy and paste the following code into the FacetQuery.java file.

    The code example performs the following tasks:

    • Imports mongodb packages and dependencies.

    • Establishes a connection to your Atlas cluster.

    • Uses the following searchMeta clauses to query the collection:

      • near to search for movies released with a pivot distance from origin of approximately three months from November 11, 1921

      • facets to request the number of movies in each genre in the genres string array field and the number of movies in the years 1910 to 1939, inclusive

    • Iterates over the cursor to print the documents that match the query.

    You can run this query using $searchMeta or using $search with the SEARCH_META aggregation variable.

    1import com.mongodb.client.MongoClient;
    2import com.mongodb.client.MongoClients;
    3import com.mongodb.client.MongoCollection;
    4import com.mongodb.client.MongoDatabase;
    5import org.bson.Document;
    6
    7import java.time.Instant;
    8import java.util.Arrays;
    9import java.util.Date;
    10
    11public class FacetQuery {
    12 public static void main(String[] args) {
    13 // connect to your Atlas cluster
    14 String uri = "<connection-string>";
    15
    16 try (MongoClient mongoClient = MongoClients.create(uri)) {
    17 // set namespace
    18 MongoDatabase database = mongoClient.getDatabase("sample_mflix");
    19 MongoCollection<Document> collection = database.getCollection("movies");
    20
    21 // define pipeline
    22 Document agg = new Document("$searchMeta",
    23 new Document( "index", "facet-tutorial")
    24 .append("facet",
    25 new Document("operator",
    26 new Document("near",
    27 new Document("path", "released")
    28 .append("origin", Date.from(Instant.parse("1921-11-01T00:00:00.000+00:00")))
    29 .append("pivot", 7776000000L)))
    30 .append("facets",
    31 new Document("genresFacet",
    32 new Document("type", "string").append("path", "genres"))
    33 .append("yearFacet",
    34 new Document("type", "number").append("path", "year")
    35 .append("boundaries", Arrays.asList(1910, 1920, 1930, 1940))
    36 ))));
    37 // run pipeline and print results
    38 collection.aggregate(Arrays.asList(agg))
    39 .forEach(doc -> System.out.println(doc.toJson()));
    40
    41 }
    42 }
    43}
    1import com.mongodb.client.MongoClient;
    2import com.mongodb.client.MongoClients;
    3import com.mongodb.client.MongoCollection;
    4import com.mongodb.client.MongoDatabase;
    5import org.bson.Document;
    6
    7import java.util.Arrays;
    8import java.util.List;
    9
    10public class FacetQuery {
    11 public static void main(String[] args) {
    12 // connect to your Atlas cluster
    13 String uri = "<CONNECTION-STRING>";
    14
    15 try (MongoClient mongoClient = MongoClients.create(uri)) {
    16 // set namespace
    17 MongoDatabase database = mongoClient.getDatabase("sample_mflix");
    18 MongoCollection<Document> collection = database.getCollection("movies");
    19
    20 // define pipeline
    21 List<Document> agg = Arrays.asList(new Document("$search",
    22 new Document("index", "facet-tutorial")
    23 .append("facet", new Document("operator", new Document("near", new Document("path", "released")
    24 .append("origin", new java.util.Date(-1520035200000L))
    25 .append("pivot", 7776000000L)))
    26 .append("facets", new Document("genresFacet", new Document("type", "string")
    27 .append("path", "genres"))
    28 .append("yearFacet", new Document("type", "number")
    29 .append("path", "year")
    30 .append("boundaries", Arrays.asList(1910L, 1920L, 1930L, 1940L)))))),
    31 new Document("$facet", new Document("meta", Arrays.asList(new Document("$replaceWith", "$$SEARCH_META"),
    32 new Document("$limit", 1L)))),
    33 new Document("$set", new Document("meta", new Document("$arrayElemAt", Arrays.asList("$meta", 0L)))));
    34 // run pipeline and print results
    35 collection.aggregate(agg)
    36 .forEach(doc -> System.out.println(doc.toJson()));
    37
    38 }
    39 }
    40}

    Note

    To run the sample code in your Maven environment, add the following above the import statements in your file.

    package com.mongodb.drivers;
  3. Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

  4. Compile and run FacetQuery.java file.

    javac FacetQuery.java
    java FacetQuery
    {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') }
    ]
    },
    yearFacet: {
    buckets: [
    { _id: 1910, count: Long('14') },
    { _id: 1920, count: Long('47') },
    { _id: 1930, count: Long('238') }
    ]
    }
    }
    }}
1

mongodb-driver-kotlin-coroutine

4.10.0 or higher version

2
  1. Create a file named FacetQuery.kt.

  2. Copy and paste the following code into the FacetQuery.kt file.

    The code example performs the following tasks:

    • Imports mongodb packages and dependencies.

    • Establishes a connection to your Atlas cluster.

    • Uses the following to query the collection:

      • near to search for movies released with a pivot distance from origin of approximately three months from November 11, 1921

      • facets to request the number of movies in each genre in the genres string array field and the number of movies in the years 1910 to 1939, inclusive

    • Prints the documents that match the query from the AggregateFlow instance.

    You can run this query using $searchMeta or using $search with the SEARCH_META aggregation variable.

    1import com.mongodb.kotlin.client.coroutine.MongoClient
    2import kotlinx.coroutines.runBlocking
    3import org.bson.Document
    4import java.time.Instant
    5import java.util.*
    6
    7fun main() {
    8 // connect to your Atlas cluster
    9 val uri = "<connection-string>"
    10 val mongoClient = MongoClient.create(uri)
    11
    12 // set namespace
    13 val database = mongoClient.getDatabase("sample_mflix")
    14 val collection = database.getCollection<Document>("movies")
    15
    16 runBlocking {
    17 // define pipeline
    18 val agg = Document(
    19 "\$searchMeta",
    20 Document("index", "facet-tutorial")
    21 .append(
    22 "facet",
    23 Document(
    24 "operator",
    25 Document(
    26 "near",
    27 Document("path", "released")
    28 .append("origin", Date.from(Instant.parse("1921-11-01T00:00:00.000+00:00")))
    29 .append("pivot", 7776000000L)
    30 )
    31 )
    32 .append(
    33 "facets",
    34 Document(
    35 "genresFacet",
    36 Document("type", "string").append("path", "genres")
    37 )
    38 .append(
    39 "yearFacet",
    40 Document("type", "number").append("path", "year")
    41 .append("boundaries", listOf(1910, 1920, 1930, 1940))
    42 )
    43 )
    44 )
    45 )
    46
    47 // run pipeline and print results
    48 val resultsFlow = collection.aggregate<Document>(
    49 listOf(agg)
    50 )
    51 resultsFlow.collect { println(it) }
    52 }
    53 mongoClient.close()
    54}
    1import com.mongodb.kotlin.client.coroutine.MongoClient
    2import kotlinx.coroutines.flow.collect
    3import kotlinx.coroutines.runBlocking
    4import org.bson.Document
    5import java.time.Instant
    6import java.util.Date
    7
    8fun main() {
    9 // Connection URI for your MongoDB Atlas cluster
    10 val uri = "<connection-string>"
    11 val mongoClient = MongoClient.create(uri)
    12
    13 // Set namespace (database and collection)
    14 val database = mongoClient.getDatabase("sample_mflix")
    15 val collection = database.getCollection<Document>("movies")
    16
    17 runBlocking {
    18 // Define the aggregation pipeline
    19 val searchStage = Document("\$search", Document("index", "facet-tutorial")
    20 .append("facet", Document("operator", Document("near", Document("path", "released")
    21 // Replace +00:00 with Z
    22 .append("origin", Date.from(Instant.parse("1921-11-01T00:00:00.000Z")))
    23 .append("pivot", 7776000000L)))
    24 .append("facets", Document("genresFacet", Document("type", "string")
    25 .append("path", "genres"))
    26 .append("yearFacet", Document("type", "number").append("path", "year")
    27 .append("boundaries", listOf(1910, 1920, 1930, 1940))))))
    28
    29 val facetStage = Document("\$facet", Document("meta", listOf(
    30 Document("\$replaceWith", "\$\$SEARCH_META"),
    31 Document("\$limit", 1)
    32 )))
    33
    34 val setStage = Document("\$set", Document("meta", Document("\$arrayElemAt", listOf("\$meta", 0))))
    35
    36 // Run the aggregation pipeline and print results
    37 val resultsFlow = collection.aggregate<Document>(
    38 listOf(searchStage, facetStage, setStage)
    39 )
    40
    41 resultsFlow.collect { println(it.toJson()) } // Convert each result to JSON and print
    42 }
    43
    44 // Close the MongoDB client
    45 mongoClient.close()
    46}
  3. Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

  4. Run the FacetQuery.kt file.

    When you run the FacetQuery.kt program in your IDE, it prints the following result:

    Document{{
    count=Document{{lowerBound=20878}},
    facet=Document{{
    genresFacet=Document{{
    buckets=[
    Document{{_id=Drama, count=12149}},
    Document{{_id=Comedy, count=6436}},
    Document{{_id=Romance, count=3274}},
    Document{{_id=Crime, count=2429}},
    Document{{_id=Thriller, count=2400}},
    Document{{_id=Action, count=2349}},
    Document{{_id=Adventure, count=1876}},
    Document{{_id=Documentary, count=1755}},
    Document{{_id=Horror, count=1432}},
    Document{{_id=Biography, count=1244}}
    ]
    }},
    yearFacet=Document{{
    buckets=[
    Document{{_id=1910, count=14}},
    Document{{_id=1920, count=47}},
    Document{{_id=1930, count=238}}
    ]
    }}
    }}
    }}
1
  1. Create a file named facet-query.js.

  2. Copy and paste the following code into the facet-query.js file.

    The code example performs the following tasks:

    • Imports mongodb, MongoDB's Node.js driver.

    • Creates an instance of the MongoClient class to establish a connection to your Atlas cluster.

    • Uses the following searchMeta clauses to query the collection:

      • near to search for movies released with a pivot distance from origin of approximately three months from November 11, 1921

      • facets to request the number of movies in each genre in the genres string array field and the number of movies in the years 1910 to 1939, inclusive

    • Iterates over the cursor to print the documents that match the query.

    You can run this query using $searchMeta or using $search with the SEARCH_META aggregation variable.

    1const { MongoClient } = require("mongodb");
    2
    3// connect to your Atlas cluster
    4const uri =
    5 "<connection-string>";
    6
    7const client = new MongoClient(uri);
    8
    9async function run() {
    10 try {
    11 await client.connect();
    12
    13 // set namespace
    14 const database = client.db("sample_mflix");
    15 const coll = database.collection("movies");
    16
    17 // define pipeline
    18 const agg = [{$searchMeta: {
    19 index: "facet-tutorial",
    20 facet: {
    21 operator: {
    22 near: {path: "released", origin: new Date("1921-11-01T00:00:00.000Z"), pivot: 7776000000}
    23 },
    24 facets: {
    25 genresFacet: {type: "string", path: "genres"},
    26 yearFacet: {type: "number", path: "year",boundaries: [1910,1920,1930,1940]}
    27 }}}}];
    28 // run pipeline
    29 const result = coll.aggregate(agg);
    30
    31 // print results
    32 await result.forEach((doc) => console.dir(JSON.stringify(doc)));
    33 } finally {
    34 await client.close();
    35 }
    36}
    37run().catch(console.dir);
    1const { MongoClient } = require("mongodb");
    2
    3// connect to your Atlas cluster
    4const uri = "<connection-string>";
    5
    6const client = new MongoClient(uri);
    7
    8async function run() {
    9 try {
    10 await client.connect();
    11
    12 // set namespace
    13 const database = client.db("sample_mflix");
    14 const coll = database.collection("movies");
    15
    16 // define pipeline
    17 const agg = [
    18 {
    19 '$search': {
    20 'index': "facet-tutorial",
    21 'facet': {
    22 'operator': {
    23 'near': {
    24 'path': 'released',
    25 'origin': new Date('Tue, 01 Nov 1921 00:00:00 GMT'),
    26 'pivot': 7776000000
    27 }
    28 },
    29 'facets': {
    30 'genresFacet': {
    31 'type': 'string',
    32 'path': 'genres'
    33 },
    34 'yearFacet': {
    35 'type': 'number',
    36 'path': 'year',
    37 'boundaries': [1910, 1920, 1930, 1940]
    38 }
    39 }
    40 }
    41 }
    42 }, {
    43 '$facet': {
    44 'meta': [
    45 {
    46 '$replaceWith': '$$SEARCH_META'
    47 }, {
    48 '$limit': 1
    49 }
    50 ]
    51 }
    52 }, {
    53 '$set': {
    54 'meta': {
    55 '$arrayElemAt': ['$meta', 0]
    56 }
    57 }
    58 }
    59 ];
    60 // run pipeline
    61 const result = coll.aggregate(agg);
    62
    63 // print results
    64 await result.forEach((doc) => console.dir(JSON.stringify(doc)));
    65 } finally {
    66 await client.close();
    67 }
    68}
    69run().catch(console.dir);
  3. Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

  4. Run the following command to query your collection:

    node facet-query.js
    '{
    "meta":{
    "count":{"lowerBound":20878},
    "facet":{
    "genresFacet":{
    "buckets":[
    {"_id":"Drama","count":12149},
    {"_id":"Comedy","count":6436},
    {"_id":"Romance","count":3274},
    {"_id":"Crime","count":2429},
    {"_id":"Thriller","count":2400},
    {"_id":"Action","count":2349},
    {"_id":"Adventure","count":1876},
    {"_id":"Documentary","count":1755},
    {"_id":"Horror","count":1432},
    {"_id":"Biography","count":1244}
    ]
    },
    "yearFacet":{
    "buckets":[
    {"_id":1910,"count":14},
    {"_id":1920,"count":47},
    {"_id":1930,"count":238}
    ]
    }
    }
    }
    }'
1
  1. Create a file named facet-query.py.

    touch facet-query.py
  2. Copy and paste the following code into the facet-query.py file.

    The following code example:

    • Imports pymongo, MongoDB's Python driver, and the dns module, which is required to connect pymongo to Atlas using a DNS seed list connection string.

    • Creates an instance of the MongoClient class to establish a connection to your Atlas cluster.

    • Uses the following to query the collection:

      • near to search for movies released with a pivot distance from origin of approximately three months from November 11, 1921

      • facets to request the number of movies in each genre in the genres string array field and the number of movies in the years 1910 to 1939, inclusive

    • Iterates over the cursor to print the documents that match the query.

    You can run this query using $searchMeta or using $search with the SEARCH_META aggregation variable.

    1import pymongo
    2import datetime
    3
    4# connect to your Atlas cluster
    5client = pymongo.MongoClient('<connection-string>')
    6
    7# define pipeline
    8pipeline = [{"$searchMeta": {
    9 "index": "facet-tutorial",
    10 "facet": {
    11 "operator": {
    12 "near": {"path": "released", "origin": datetime.datetime(1921, 11, 1, 0, 0, 0, 0), "pivot": 7776000000}
    13 },
    14 "facets": {
    15 "genresFacet": {"type": "string", "path": "genres"},
    16 "yearFacet" : {"type" : "number", "path" : "year", "boundaries" : [1910,1920,1930,1940]}
    17 }}}}]
    18# run pipeline
    19result = client["sample_mflix"]["movies"].aggregate(pipeline)
    20
    21# print results
    22for i in result:
    23 print(i)
    1import pymongo
    2from datetime import datetime, timezone # Import timezone for tzinfo=timezone.utc
    3
    4# Connect to your Atlas cluster
    5client = pymongo.MongoClient("<connection-string>")
    6
    7# Define pipeline
    8pipeline = [{
    9 '$search': {
    10 'index': 'facet-tutorial',
    11 'facet': {
    12 'operator': {
    13 'near': {
    14 'path': 'released',
    15 'origin': datetime(1921, 11, 1, 0, 0, 0, tzinfo=timezone.utc), # Corrected timezone
    16 'pivot': 7776000000
    17 }
    18 },
    19 'facets': {
    20 'genresFacet': {
    21 'type': 'string', 'path': 'genres'
    22 },
    23 'yearFacet': {
    24 'type': 'number', 'path': 'year', 'boundaries': [1910, 1920, 1930, 1940]
    25 }
    26 }
    27 }
    28 }
    29}, {
    30 '$facet': {
    31 'meta': [
    32 {'$replaceWith': '$$SEARCH_META'},
    33 {'$limit': 1}
    34 ]
    35 }
    36}, {
    37 '$set': {
    38 'meta': {'$arrayElemAt': ['$meta', 0]}
    39 }
    40}]
    41# Run pipeline
    42result = client["sample_mflix"]["movies"].aggregate(pipeline)
    43
    44# Print results
    45for doc in result:
    46 print(doc)
  3. Before you run the sample, replace <connection-string> with your Atlas connection string. Ensure that your connection string includes your database user's credentials. To learn more, see Connect via Drivers.

  4. Run the following command to query your collection:

    python facet-query.py
    {
    'meta': {
    'count': {'lowerBound': 20878},
    'facet': {
    'genresFacet': {
    'buckets': [
    {'_id': 'Drama', 'count': 12149},
    {'_id': 'Comedy', 'count': 6436},
    {'_id': 'Romance', 'count': 3274},
    {'_id': 'Crime', 'count': 2429},
    {'_id': 'Thriller', 'count': 2400},
    {'_id': 'Action', 'count': 2349},
    {'_id': 'Adventure', 'count': 1876},
    {'_id': 'Documentary', 'count': 1755},
    {'_id': 'Horror', 'count': 1432},
    {'_id': 'Biography', 'count': 1244}
    ]
    },
    'yearFacet': {
    'buckets': [
    {'_id': 1910, 'count': 14},
    {'_id': 1920, 'count': 47},
    {'_id': 1930, 'count': 238}
    ]
    }
    }
    }
    }

The results show metadata results for two types of facet search. The genresFacet document shows the number of movies in each genre and the yearFacet document shows a count of the number of movies within the boundaries:

  • 1910, inclusive lower bound the 1910 bucket

  • 1920, exclusive upper bound for the 1910 bucket and inclusive lower bound for the 1920 bucket

  • 1930, exclusive upper bound for the 1920 bucket and inclusive lower bound for the 1930 bucket

You can learn more about facet in Atlas Search with our course or video.

To learn more about using facets in Atlas Search, take Unit 9 of the Intro To MongoDB Course on MongoDB University. The 1.5 hour unit includes an overview of Atlas Search and lessons on creating Atlas Search indexes, running $search queries using compound operators, and grouping results using facet.

Follow along with this video to learn about how you can create and use a numeric and string facet in your query to group results and retrieve a count of the results in the groups.

Duration: 11 Minutes