Overview
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.
Sample Data
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:
[] public class Movie { [] 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!; [] public float[] PlotEmbedding { get; set; } = null!; public double Score { get; set; } [] public string PaginationToken { get; set; } = null!; }
The Movie class references the following Imdb class, which
models the nested imdb field in each document:
[] 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.
Create a MongoDB Search Index
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.
MongoDB Search Operators
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.
Autocomplete
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.
Compound
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.ratingfield exists on the documentThe
ratedfield value is not"G"The
yearfield 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.
EmbeddedDocument
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:
[] public class Restaurant { [] 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!; }
[] 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.
Equals
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.
Exists
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.
GeoShape
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:
[] public class Theater { [] public ObjectId Id { get; set; } public int TheaterId { get; set; } public TheaterLocation Location { get; set; } = null!; }
[] public class TheaterLocation { [] 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.
GeoWithin
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.
In
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" : "..." } } ...
MoreLikeThis
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.
Near
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.
Phrase
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.
QueryString
Use the QueryString() method to search for documents using a
string with the following operators and delimiters:
ANDORNOT()
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.
Range
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.
Regex
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.
Span
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.
Text
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.
Wildcard
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.