Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /

MongoDB Search

In this guide you can learn how to use the Search builder to build a $search aggregation pipeline stage with the MongoDB .NET/C# Driver.

To learn more about the $search pipeline stage, see $search.

Note

Only Available on Atlas for MongoDB v4.2 and Later

The $search aggregation-pipeline operator is available only for collections hosted on MongoDB Atlas clusters running MongoDB v4.2 or later that are covered by an MongoDB Search index. To learn more about the required setup and the functionality of this operator, see the MongoDB Search documentation.

The examples in this guide use the movies collection from the sample_mflix database. Documents in this collection contain information about films, including their title, plot, genre, and ratings. The following Movie class models the documents in this collection:

[BsonIgnoreExtraElements]
public class Movie
{
[BsonId]
public ObjectId Id { get; set; }
public string Title { get; set; } = null!;
public string Plot { get; set; } = null!;
public string[] Genres { get; set; } = null!;
public int Year { get; set; }
public string Rated { get; set; } = null!;
public Imdb Imdb { get; set; } = null!;
[BsonElement("plot_embedding")]
public float[] PlotEmbedding { get; set; } = null!;
public double Score { get; set; }
[BsonElement("paginationToken")]
public string PaginationToken { get; set; } = null!;
}

The Movie class references the following Imdb class, which models the nested imdb field in each document:

[BsonIgnoreExtraElements]
public class Imdb
{
public double Rating { get; set; }
public int Votes { get; set; }
public int Id { get; set; }
}

Note

Camel-Case Field Names in Sample Data

The documents in the movies collection use the camel-case naming convention. The examples in this guide use a ConventionPack to deserialize the fields in the collection into Pascal case and map them to the properties in the Movie class.

To learn more about custom serialization, see Custom Serialization.

Some examples in this guide use additional collections and model classes, which the relevant sections introduce. All collections are from the sample datasets provided by Atlas. See Quick Start to learn how to create a free MongoDB cluster and load this sample data.

Before you can perform a search on an Atlas collection, you must first create an Atlas Search index on the collection. A MongoDB Search index is a data structure that categorizes data in a searchable format.

To learn how to create a MongoDB Search Index see the Create a MongoDB Search Index Atlas guide.

The Search class contains methods you can use to perform $search operations. For a full list of available $search operators, see the Operators and Collectors Atlas guide.

Use the Autocomplete() method to search for a word or phrase that contains a sequence of characters from an incomplete input string.

The following example performs an autocomplete query on the title field for text that starts with the string "Gravity":

var result = moviesCollection.Aggregate()
.Search(Builders<Movie>.Search.Autocomplete(m => m.Title, "Gravity"), indexName: "movietitles")
.ToList();
...
{ "_id" : ObjectId("..."), "title" : "Gravity", "plot" : "...", "genres" : ["Drama", "Sci-Fi", "Thriller"], "year" : 2013, "rated" : "PG-13", "imdb" : { "rating" : 7.7, "votes" : "...", "id" : "..." } }
...

Note

Index for Autocomplete Queries

You must create a MongoDB Search index that supports autocompletion to successfully perform autocomplete queries. To learn more, see How to Index Fields for Autocompletion in the Atlas documentation.

After you create the MongoDB Search index, you must pass the index name to the Autocomplete() method, as shown in the preceding example.

To learn more about the autocomplete operator, see the autocomplete Atlas guide.

Use the Compound() method to combine two or more operators into a single search.

The following example searches the movies collection for any documents that match all of the following criteria:

  • The imdb.rating field exists on the document

  • The rated field value is not "G"

  • The year field has a value greater than 2000

var result = moviesCollection.Aggregate()
.Search(Builders<Movie>.Search.Compound()
.Must(Builders<Movie>.Search.Exists(m => m.Imdb.Rating))
.MustNot(Builders<Movie>.Search.Equals(m => m.Rated, "G"))
.Must(Builders<Movie>.Search.Range(m => m.Year, SearchRangeBuilder.Gt(2000))))
.ToList();
...
{ "_id" : ObjectId("..."), "title" : "The Dark Knight", "plot" : "...", "genres" : ["Action", "Crime", "Drama"], "year" : 2008, "rated" : "PG-13", "imdb" : { "rating" : 9.0, "votes" : "...", "id" : "..." } }
{ "_id" : ObjectId("..."), "title" : "Inception", "plot" : "...", "genres" : ["Action", "Adventure", "Sci-Fi"], "year" : 2010, "rated" : "PG-13", "imdb" : { "rating" : 8.8, "votes" : "...", "id" : "..." } }
...

To learn more about the compound operator, see the compound Atlas guide.

Use the EmbeddedDocument() method to perform search operations on documents within a field's array value.

Note

To search on embedded documents, you must create an embeddedDocument index on the array field.

To learn how to define an embeddedDocument index, see Define the Index for the embeddedDocument Type in the Atlas documentation.

This example uses the restaurants collection from the sample_restaurants database. The following classes model the documents in that collection:

[BsonIgnoreExtraElements]
public class Restaurant
{
[BsonId]
public ObjectId Id { get; set; }
public string Name { get; set; } = null!;
public string Cuisine { get; set; } = null!;
public string Borough { get; set; } = null!;
public List<GradeEntry> Grades { get; set; } = null!;
}
[BsonIgnoreExtraElements]
public class GradeEntry
{
public string Grade { get; set; } = null!;
public int? Score { get; set; }
}

The following example searches that collection for any restaurants whose grades array contains an entry with a grade field value of "A":

var result = restaurantsCollection.Aggregate()
.Search(Builders<Restaurant>.Search.EmbeddedDocument(
r => r.Grades,
Builders<GradeEntry>.Search.Equals(g => g.Grade, "A")
), indexName: "restaurantsembedded").ToList();
...
{ "_id" : ObjectId("..."), "name" : "Riviera Caterer", "cuisine" : "American", "borough" : "Brooklyn", "grades" : [{ "grade" : "A", "score" : 5 }, { "grade" : "B", "score" : 23 }] }
...

To learn more about the embeddedDocument operator, see the embeddedDocument Atlas guide.

Use the Equals() method to check whether a field matches a specified value.

The following example searches the movies collection for any documents in which the value of the year field is 2000:

var result = moviesCollection.Aggregate()
.Search(Builders<Movie>.Search.Equals(m => m.Year, 2000))
.ToList();
...
{ "_id" : ObjectId("..."), "title" : "Gladiator", "plot" : "...", "genres" : ["Action", "Adventure", "Drama"], "year" : 2000, "rated" : "R", "imdb" : { "rating" : 8.5, "votes" : "...", "id" : "..." } }
{ "_id" : ObjectId("..."), "title" : "Cast Away", "plot" : "...", "genres" : ["Adventure", "Drama", "Romance"], "year" : 2000, "rated" : "PG-13", "imdb" : { "rating" : 7.8, "votes" : "...", "id" : "..." } }
...

To learn more about the equals operator, see the equals Atlas guide.

Use the Exists() method to search for documents in which a specified indexed field name exists. If the specified field exists but is not indexed, the document is not included with the result set.

The following example searches the movies collection for any documents in which the imdb.rating field exists:

var result = moviesCollection.Aggregate()
.Search(Builders<Movie>.Search.Exists(m => m.Imdb.Rating))
.ToList();
...
{ "_id" : ObjectId("..."), "title" : "The Godfather", "plot" : "...", "genres" : ["Crime", "Drama"], "year" : 1972, "rated" : "R", "imdb" : { "rating" : 9.2, "votes" : "...", "id" : "..." } }
{ "_id" : ObjectId("..."), "title" : "The Shawshank Redemption", "plot" : "...", "genres" : ["Drama"], "year" : 1994, "rated" : "R", "imdb" : { "rating" : 9.3, "votes" : "...", "id" : "..." } }
...

To learn more about the exists operator, see the exists Atlas guide.

Use the GeoShape() method to search for documents in relation to a given geometry. When specifying the coordinates to search, longitude must be specified first, followed by latitude. Longitude values can be between -180 and 180, inclusive. Latitude values can be between -90 and 90, inclusive.

Note

MongoDB Search does not support the following:

  • Non-default coordinate reference system (CRS)

  • Planar XY coordinate system (2 dimensional)

  • Coordinate pairs Point notation (pointFieldName: [12, 34])

This example uses the theaters collection from the sample_mflix database. The following classes model the documents in that collection:

[BsonIgnoreExtraElements]
public class Theater
{
[BsonId]
public ObjectId Id { get; set; }
public int TheaterId { get; set; }
public TheaterLocation Location { get; set; } = null!;
}
[BsonIgnoreExtraElements]
public class TheaterLocation
{
[BsonElement("geo")]
public GeoJsonPoint<GeoJson2DGeographicCoordinates> Geo { get; set; } = null!;
}

The following example searches that collection for all documents in which the coordinates in the location.geo field intersect with a specified polygon in the Minneapolis, MN area:

GeoJsonPolygon<GeoJson2DGeographicCoordinates> searchArea = new(new(new(new GeoJson2DGeographicCoordinates[]
{
new(-93.5, 44.7),
new(-93.5, 45.0),
new(-93.0, 45.0),
new(-93.0, 44.7),
new(-93.5, 44.7),
})));
var result = theatersCollection.Aggregate()
.Search(Builders<Theater>.Search.GeoShape(
t => t.Location.Geo, GeoShapeRelation.Intersects, searchArea),
indexName: "theatersgeo")
.ToList();
...
{ "_id" : ObjectId("..."), "theaterId" : 1000, "location" : { "geo" : { "type" : "Point", "coordinates" : [-93.24565, 44.85466] } } }
...

To learn more about the geoShape operator, see the geoShape Atlas guide.

Use the GeoWithin() method to search for documents in which the coordinates of their specified GeoJSON field are within a given geometry. You can search for points that are within a:

  • Circle

  • Bounding box

  • Polygon

When specifying the coordinates to search, longitude must be specified first, followed by latitude. Longitude values can be between -180 and 180, inclusive. Latitude values can be between -90 and 90, inclusive.

Note

MongoDB Search does not support the following:

  • Non-default coordinate reference system (CRS)

  • Planar XY coordinate system (2 dimensional)

  • Coordinate pairs Point notation (pointFieldName: [12, 34])

The following example searches the theaters collection for all documents in which the coordinates in the location.geo field fall within a specified polygon:

GeoJsonPolygon<GeoJson2DGeographicCoordinates> searchArea = new(new(new(new GeoJson2DGeographicCoordinates[]
{
new(-94.0, 44.5),
new(-94.0, 45.2),
new(-92.5, 45.2),
new(-92.5, 44.5),
new(-94.0, 44.5),
})));
var result = theatersCollection.Aggregate()
.Search(Builders<Theater>.Search.GeoWithin(t => t.Location.Geo, searchArea),
indexName: "theatersgeo")
.ToList();
...
{ "_id" : ObjectId("..."), "theaterId" : 1000, "location" : { "geo" : { "type" : "Point", "coordinates" : [-93.24565, 44.85466] } } }
...

To learn more about the geoWithin operator, see the geoWithin Atlas guide.

Use the In() method to search for documents with field values that match a list of specified values.

The following example searches the movies collection for documents that have a genres array containing either "Action" or "Comedy":

var result = moviesCollection.Aggregate()
.Search(Builders<Movie>.Search.In(m => m.Genres, new[] { "Action", "Comedy" }))
.ToList();
...
{ "_id" : ObjectId("..."), "title" : "Home Alone", "plot" : "...", "genres" : ["Comedy", "Family"], "year" : 1990, "rated" : "PG", "imdb" : { "rating" : 7.4, "votes" : "...", "id" : "..." } }
{ "_id" : ObjectId("..."), "title" : "Die Hard", "plot" : "...", "genres" : ["Action", "Thriller"], "year" : 1988, "rated" : "R", "imdb" : { "rating" : 8.2, "votes" : "...", "id" : "..." } }
...

Use the MoreLikeThis() method to search for documents that are similar to an input document.

This example uses the following class to specify the input document for the search:

public class MovieSearch
{
public string Plot { get; set; } = null!;
}

The following example searches the movies collection for documents similar to an object in which the value of the plot field is "time travel":

var searchDocument = new MovieSearch()
{
Plot = "time travel",
};
var result = moviesCollection.Aggregate()
.Search(Builders<Movie>.Search.MoreLikeThis(searchDocument))
.ToList();
...
{ "_id" : ObjectId("..."), "title" : "Thrill Seekers", "plot" : "...", "genres" : ["Action", "Sci-Fi", "Thriller"], "year" : 1999, "rated" : "...", "imdb" : { "rating" : "...", "votes" : "...", "id" : "..." } }
{ "_id" : ObjectId("..."), "title" : "About Time", "plot" : "...", "genres" : ["Drama", "Fantasy", "Romance"], "year" : 2013, "rated" : "R", "imdb" : { "rating" : 7.8, "votes" : "...", "id" : "..." } }
...

To learn more about the moreLikeThis operator, see the moreLikeThis Atlas guide.

Use the Near() method to search for documents in which a specified field is near a given value. You can perform the search on:

  • A number field

  • A date field

  • A geographic point

The following example searches the movies collection for documents in which the value of the imdb.rating field is near 8.5. The documents are returned in order based on how close the value is to 8.5:

var result = moviesCollection.Aggregate()
.Search(Builders<Movie>.Search.Near(m => m.Imdb.Rating, 8.5, 1))
.ToList();
...
{ "_id" : ObjectId("..."), "title" : "The Dark Knight", "plot" : "...", "genres" : ["Action", "Crime", "Drama"], "year" : 2008, "rated" : "PG-13", "imdb" : { "rating" : 9.0, "votes" : "...", "id" : "..." } }
{ "_id" : ObjectId("..."), "title" : "The Godfather", "plot" : "...", "genres" : ["Crime", "Drama"], "year" : 1972, "rated" : "R", "imdb" : { "rating" : 9.2, "votes" : "...", "id" : "..." } }
...

To learn more about the near operator, see the near Atlas guide.

Use the Phrase() method to search for documents in which a specified field contains an input string.

The following example searches the movies collection for documents in which the plot field contains the phrase "time travel":

var result = moviesCollection.Aggregate()
.Search(Builders<Movie>.Search.Phrase(m => m.Plot, "time travel"))
.ToList();
...
{ "_id" : ObjectId("..."), "title" : "The Time Traveler's Wife", "plot" : "...", "genres" : ["Drama", "Fantasy", "Romance"], "year" : 2009, "rated" : "PG-13", "imdb" : { "rating" : 7.1, "votes" : "...", "id" : "..." } }
{ "_id" : ObjectId("..."), "title" : "Safety Not Guaranteed", "plot" : "...", "genres" : ["Comedy", "Drama", "Romance"], "year" : 2012, "rated" : "R", "imdb" : { "rating" : 7, "votes" : "...", "id" : "..." } }
...

You can also search the collection for documents that contain either "time travel" or "space adventure" in the plot field:

var result = moviesCollection.Aggregate()
.Search(Builders<Movie>.Search.Phrase(m => m.Plot, new List<string>() { "time travel", "space adventure" }))
.ToList();
...
{ "_id" : ObjectId("..."), "title" : "The Time Traveler's Wife", "plot" : "...", "genres" : ["Drama", "Fantasy", "Romance"], "year" : 2009, "rated" : "PG-13", "imdb" : { "rating" : 7.1, "votes" : "...", "id" : "..." } }
{ "_id" : ObjectId("..."), "title" : "Safety Not Guaranteed", "plot" : "...", "genres" : ["Comedy", "Drama", "Romance"], "year" : 2012, "rated" : "R", "imdb" : { "rating" : 7, "votes" : "...", "id" : "..." } }
...

To learn more about the phrase operator, see the phrase Atlas guide.

Use the QueryString() method to search for documents using a string with the following operators and delimiters:

  • AND

  • OR

  • NOT

  • ()

The following example searches the movies collection for documents in which the value of the plot field matches each of the following criteria:

  • Contains the string "time" or the string "space"

  • Does not contain the string "comedy"

var result = moviesCollection.Aggregate()
.Search(Builders<Movie>.Search.QueryString(m => m.Plot, "(time OR space) AND NOT comedy"))
.ToList();
...
{ "_id" : ObjectId("..."), "title" : "Interstellar", "plot" : "...", "genres" : ["Adventure", "Drama", "Sci-Fi"], "year" : 2014, "rated" : "PG-13", "imdb" : { "rating" : 8.7, "votes" : "...", "id" : "..." } }
{ "_id" : ObjectId("..."), "title" : "Tomorrowland", "plot" : "...", "genres" : ["Action", "Adventure", "Family"], "year" : 2015, "rated" : "PG", "imdb" : { "rating" : 6.6, "votes" : "...", "id" : "..." } }
...

To learn more about the queryString operator, see the queryString Atlas guide.

Use the Range() method to search for documents in which the value of a specified field falls within a given numeric or date range.

The following example searches the movies collection for all documents with a year value greater than 2000 and less than 2010:

var result = moviesCollection.Aggregate()
.Search(Builders<Movie>.Search
.Range(m => m.Year, SearchRangeBuilder.Gt(2000).Lt(2010)))
.ToList();
...
{ "_id" : ObjectId("..."), "title" : "The Dark Knight", "plot" : "...", "genres" : ["Action", "Crime", "Drama"], "year" : 2008, "rated" : "PG-13", "imdb" : { "rating" : 9.0, "votes" : "...", "id" : "..." } }
{ "_id" : ObjectId("..."), "title" : "The Departed", "plot" : "...", "genres" : ["Crime", "Drama", "Thriller"], "year" : 2006, "rated" : "R", "imdb" : { "rating" : 8.5, "votes" : "...", "id" : "..." } }
...

To learn more about the range operator, see the range Atlas guide.

Use the Regex() method to search for documents using a regular expression.

The following example searches the movies collection for documents in which the value of the title field contains exactly six letters:

var regex = "[A-Za-z]{6}";
var result = moviesCollection.Aggregate()
.Search(Builders<Movie>.Search.Regex(m => m.Title, regex,
allowAnalyzedField: true))
.ToList();
...
{ "_id" : ObjectId("..."), "title" : "Gandhi", "plot" : "...", "genres" : ["Biography", "Drama", "History"], "year" : 1982, "rated" : "PG", "imdb" : { "rating" : 8.0, "votes" : "...", "id" : "..." } }
{ "_id" : ObjectId("..."), "title" : "Batman", "plot" : "...", "genres" : ["Action", "Adventure"], "year" : 1989, "rated" : "PG-13", "imdb" : { "rating" : 7.5, "votes" : "...", "id" : "..." } }
...

Note

By default the regex operator cannot run on an analyzed field. You can allow it to run on an analyzed field by setting allowAnalyzedField option to true, as follows:

var result = moviesCollection.Aggregate()
.Search(Builders<Movie>.Search.Regex(m => m.Title, regex,
allowAnalyzedField: true))
.ToList();

Setting the allowAnalyzedField option to true may lead to unexpected search results. To learn more, see regex Behavior.

To learn more about the regex operator, see the regex Atlas guide.

Use the Span() method to search for text search matches within regions of a field. You can use this method to find strings which are near each other to specified degrees of precision.

Note

The span operator is more computationally intensive than other operators because queries must keep track of positional information.

The following example searches the movies collection for documents in which the value of the plot field contains the strings "time" and "travel" within one word of each other:

var searchTerms = new[]
{
Builders<Movie>.SearchSpan.Term(m => m.Plot, "time"),
Builders<Movie>.SearchSpan.Term(m => m.Plot, "travel")
};
var result = moviesCollection.Aggregate()
.Search(Builders<Movie>.Search.Span(Builders<Movie>.SearchSpan.Near(searchTerms, 1)))
.ToList();
...
{ "_id" : ObjectId("..."), "title" : "The Time Traveler's Wife", "plot" : "...", "genres" : ["Drama", "Fantasy", "Romance"], "year" : 2009, "rated" : "PG-13", "imdb" : { "rating" : 7.1, "votes" : "...", "id" : "..." } }
{ "_id" : ObjectId("..."), "title" : "About Time", "plot" : "...", "genres" : ["Drama", "Fantasy", "Romance"], "year" : 2013, "rated" : "R", "imdb" : { "rating" : 7.8, "votes" : "...", "id" : "..." } }
...

To learn more about the span operator, see the span Atlas guide.

Use the Text() method to search a document for a given string or array of strings. If there are multiple terms in a given string, MongoDB Search also looks for a match for each term in the string separately.

The following example searches the movies collection for documents in which the value of the plot field contains the string "secret agent":

var result = moviesCollection.Aggregate()
.Search(Builders<Movie>.Search.Text(m => m.Plot, "secret agent"))
.ToList();
...
{ "_id" : ObjectId("..."), "title" : "Spy Kids", "plot" : "...", "genres" : ["Action", "Adventure", "Comedy"], "year" : 2001, "rated" : "PG", "imdb" : { "rating" : 5.4, "votes" : "...", "id" : "..." } }
{ "_id" : ObjectId("..."), "title" : "The Spy Who Loved Me", "plot" : "...", "genres" : ["Action", "Adventure", "Thriller"], "year" : 1977, "rated" : "PG", "imdb" : { "rating" : 7.1, "votes" : "...", "id" : "..." } }
...

Tip

If your search string contains multiple terms, the method also looks for a match for each term in the string separately.

To learn more about the text operator, see the text Atlas guide.

Use the Wildcard() method to search for documents using special characters in your search string that can match any character. You can use the following characters in your search:

Character
Description

?

Matches any single character

*

Matches 0 or more characters

\

Escape character

The following example searches for documents in which the value of the title field contains the string "Amer" followed by any other characters:

var result = moviesCollection.Aggregate()
.Search(Builders<Movie>.Search.Wildcard(m => m.Title, "Amer*", allowAnalyzedField: true))
.ToList();
...
{ "_id" : ObjectId("..."), "title" : "American Beauty", "plot" : "...", "genres" : ["Drama"], "year" : 1999, "rated" : "R", "imdb" : { "rating" : 8.4, "votes" : "...", "id" : "..." } }
{ "_id" : ObjectId("..."), "title" : "American Gangster", "plot" : "...", "genres" : ["Biography", "Crime", "Drama"], "year" : 2007, "rated" : "R", "imdb" : { "rating" : 7.8, "votes" : "...", "id" : "..." } }
...

Note

By default the wildcard operator cannot run on an analyzed field. You can allow it to run on an analyzed field by setting allowAnalyzedField option to true, as follows:

var result = moviesCollection.Aggregate()
.Search(Builders<Movie>.Search.Wildcard(m => m.Title, "Amer*", allowAnalyzedField: true))
.ToList();

Setting the allowAnalyzedField option to true may lead to unexpected search results. To learn more, see wildcard Behavior.

To learn more about the wildcard operator, see the wildcard Atlas guide.

Back

Operations with Builders

On this page