Docs Menu
Docs Home
/ / /
C#/.NET
/

Atlas Search

On this page

  • Overview
  • Create an Atlas Search Index
  • Atlas Search Operators
  • Autocomplete
  • Compound
  • EmbeddedDocument
  • Equals
  • Exists
  • GeoShape
  • GeoWithin
  • MoreLikeThis
  • Near
  • Phrase
  • QueryString
  • Range
  • Regex
  • Span
  • Text
  • Wildcard

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 Atlas search index. To learn more about the required setup and the functionality of this operator, see the Atlas Search documentation.

The examples in this guide use the following documents in a collection called guitars:

{ "_id": 1, "make": "Fender", "description": "Classic guitars known for their versatility.", "establishedYear": 1946, "in_stock": true, "rating": 9 }
{ "_id": 2, "make": "Gibson", "description": "Classic guitars known for their rich, full tones.", "establishedYear": 1902, "in_stock": true, "rating": 8 }
{ "_id": 3, "make": "PRS", "description": "High-end guitars known for their quality.", "establishedYear": 1985, "in_stock": true, "rating": 9 }
{ "_id": 4, "make": "Kiesel", "description": "Quality guitars made only for custom orders.", "establishedYear": 2015, "in_stock": false }
{ "_id": 5, "make": "Ibanez", "description": "Well-crafted guitars used by many professional guitarists.", "establishedYear": 1957, "in_stock": true, "rating": 7 }
{ "_id": 6, "make": "Strandberg", "description": "Modern guitars known for their headless models.", "establishedYear": 1982, "in_stock": false }

The following Guitar class models the documents in this collection.

public class Guitar
{
public int Id { get; set; }
public string Make { get; set; }
public List<string> Models { get; set; }
public int EstablishedYear { get; set; }
[BsonElement("in_stock")]
public bool InStock { get; set; }
public int? Rating { get; set; }
}

Note

The documents in the guitars 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 Guitar class.

To learn more about custom serialization, see Custom Serialization.

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

To learn how to create an Atlas Search Index see the Create an Atlas 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 search on the guitars collection using the string "Gib" in the make field.

var result = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.Autocomplete(g => g.Make, "Gib"), indexName: "guitarmakes")
.ToList();

Note

If the field you are searching on is indexed by a search index, you must pass the index name to the Autocomplete call. If a search index does not exist, the default index is used.

The search returns the following document:

{ "_id" : 2, "make" : "Gibson", "description" : "Classic guitars known for their rich, full tones.", "establishedYear" : 1902, "in_stock" : true, "rating" : 8 }

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 guitars collection for any documents that match all of the following criteria:

  • The rating field exists on the document

  • The in_stock field is not false

  • The establishedYear field has a value greater than 1940

var result = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.Compound()
.Must(Builders<Guitar>.Search.Exists(g => g.Rating))
.MustNot(Builders<Guitar>.Search.Equals(g => g.InStock, false))
.Must(Builders<Guitar>.Search.Range(g => g.EstablishedYear, SearchRangeBuilder.Gt(1940))))
.ToList();

The search returns the following documents:

{ "_id" : 1, "make" : "Fender", "description" : "...", "establishedYear" : 1946, "in_stock" : true, "rating" : 9 }
{ "_id" : 3, "make" : "PRS", "description" : "...", "establishedYear" : 1985, "in_stock" : true, "rating" : 9 }
{ "_id" : 5, "make" : "Ibanez", "description" : "...", "establishedYear" : 1957, "in_stock" : true, "rating" : 7 }

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.

Consider that some documents in the guitars collection have added a productDetails field that holds an array of product detail objects:

{ "_id": 1, "make": "Fender", "description": "...", "establishedYear": 1946, "in_stock": true, "rating": 9, "productDetails": [{"product_id": 1234, "serial": "YZ5678"}] }
{ "_id": 2, "make": "Gibson", "description": "...", "establishedYear": 1902, "in_stock": true, "rating": 8 }
{ "_id": 3, "make": "PRS", "description": "...", "establishedYear": 1985, "in_stock": true, "rating": 9, "productDetails": [{"product_id": 9870, "serial": "AB5555"}] }
{ "_id": 4, "make": "Kiesel", "description": "...", "establishedYear": 2015, "in_stock": false }
{ "_id": 5, "make": "Ibanez", "description": "...", "establishedYear": 1957, "in_stock": true, "rating": 7, "productDetails": [{"product_id": 5432, "serial": "ZZ1234"}] }
{ "_id": 6, "make": "Strandberg", "description": "...", "establishedYear": 1982, "in_stock": false }

After creating an embeddedDocument index on the productDetails field, you can perform Atlas search operations on documents in that field. The following example performs a text search on the productDetails array fields and returns any documents with a serial field value of "YZ5678":

var result = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.EmbeddedDocument(
g => g.ProductDetails,
Builders<ProductDetails>.Search.Text(p => p.Serial, "YZ5678")
)).ToList();
return result;

The search returns the following document:

{ "_id" : 1, "make" : "Fender", "description" : "Classic guitars known for their versatility.", "establishedYear" : 1946, "in_stock" : true, "rating" : 9, "productDetails" : [{ "product_id" : 1234, "serial" : "YZ5678" }] }

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 guitars collection for any documents in which the value of the in_stock field is true.

var result = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.Equals(g => g.InStock, true))
.ToList();

The search returns the following documents:

{ "_id" : 1, "make" : "Fender", "description" : "...", "establishedYear" : 1946, "in_stock" : true, "rating" : 9 }
{ "_id" : 2, "make" : "Gibson", "description" : "...", "establishedYear" : 1902, "in_stock" : true, "rating" : 8 }
{ "_id" : 3, "make" : "PRS", "description" : "...", "establishedYear" : 1985, "in_stock" : true, "rating" : 9 }
{ "_id" : 5, "make" : "Ibanez", "description" : "...", "establishedYear" : 1957, "in_stock" : true, "rating" : 7 }

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 guitars collection for any documents in which the rating field exists.

var result = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.Exists(g => g.Rating))
.ToList();

The search returns the following documents:

{ "_id" : 1, "make" : "Fender", "description" : "...", "establishedYear" : 1946, "in_stock" : true, "rating" : 9 }
{ "_id" : 2, "make" : "Gibson", "description" : "...", "establishedYear" : 1902, "in_stock" : true, "rating" : 8 }
{ "_id" : 3, "make" : "PRS", "description" : "...", "establishedYear" : 1985, "in_stock" : true, "rating" : 9 }
{ "_id" : 5, "make" : "Ibanez", "description" : "...", "establishedYear" : 1957, "in_stock" : true, "rating" : 7 }

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

Atlas 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])

Consider some documents in the guitars collection have added an in_stock_location field. The changed documents in the collection now look as follows:

{ "_id": 1, "make": "Fender", "description": "...", "establishedYear": 1946, "in_stock": true, "in_stock_location": { "type": "Point", "coordinates": [ -73.93615, 40.69791 ]}, "rating": 9 }
{ "_id": 2, "make": "Gibson", "description": "...", "establishedYear": 1902, "in_stock": true, "in_stock_location": { "type": "Point", "coordinates": [ 47.6062, 122.321 ]}, "rating": 8 }

The following example searches for all documents in which the coordinates in the in_stock_location field intersect with a specified polygon:

GeoJsonPolygon<GeoJson2DGeographicCoordinates> searchArea = new(new(new(new GeoJson2DGeographicCoordinates[]
{
new(-72.93615, 41.69791),
new(-72.93615, 40.59791),
new(-74.93615, 40.59791),
new(-74.93615, 41.69791),
new(-72.93615, 41.69791),
})));
var result = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.GeoShape(g => g.InStockLocation, GeoShapeRelation.Intersects, searchArea))
.ToList();

The search returns the following document:

{ "_id" : 1, "make" : "Fender", "description" : "...", "establishedYear" : 1946, "in_stock" : true, "in_stock_location" : { "type" : "Point", "coordinates" : ["-73.93615", "40.69791"] }, "rating" : 9 }

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

Atlas 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])

Consider some documents in the guitars collection have added an in_stock_location field. The changed documents in the collection now look as follows:

{ "_id": 1, "make": "Fender", "description": "...", "establishedYear": 1946, "in_stock": true, "in_stock_location": { "type": "Point", "coordinates": [ -73.93615, 40.69791 ]}, "rating": 9 }
{ "_id": 2, "make": "Gibson", "description": "...", "establishedYear": 1902, "in_stock": true, "in_stock_location": { "type": "Point", "coordinates": [ 47.6062, 122.321 ]}, "rating": 8 }

The following example searches for all documents in which the coordinates in the in_stock_location field falls within a specified polygon:

GeoJsonPolygon<GeoJson2DGeographicCoordinates> searchArea = new(new(new(new GeoJson2DGeographicCoordinates[]
{
new(-74.3994140625, 40.5305017757),
new(-74.7290039063, 40.5805846641),
new(-74.7729492188, 40.9467136651),
new(-74.0698242188, 41.1290213475),
new(-73.65234375, 40.9964840144),
new(-72.6416015625, 40.9467136651),
new(-72.3559570313, 40.7971774152),
new(-74.3994140625, 40.5305017757),
})));
var result = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.GeoWithin(g => g.InStockLocation, searchArea))
.ToList();

The search returns the following document:

{ "_id" : 1, "make" : "Fender", "description" : "Classic guitars known for their versatility.", "establishedYear" : 1946, "in_stock" : true, "in_stock_location" : { "type" : "Point", "coordinates" : ["-73.93615", "40.69791"] }, "rating" : 9 }

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

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

The following example searches the guitars collection for documents that are similar to an object in which the value of the Description field is "high quality."

var searchDocument = new GuitarSearch()
{
Description = "high quality",
};
var result = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.MoreLikeThis(searchDocument))
.ToList();

The search returns the following documents:

{ "_id" : 3, "make" : "PRS", "description" : "High-end guitars known for their quality.", "establishedYear" : 1985, "in_stock" : true, "rating" : 9 }
{ "_id" : 4, "make" : "Kiesel", "description" : "Quality guitars made only for custom orders.", "establishedYear" : 2015, "in_stock" : false, "rating" : null }

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 guitars collection for documents in which the value of the rating field is near 9. The documents are returned in order based on how close the value is to the number 9.

var result = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.Near(g => g.Rating, 9, 1))
.ToList();

The search returns the following documents:

{ "_id" : 1, "make" : "Fender", "description" : "...", "establishedYear" : 1946, "in_stock" : true, "rating" : 9 }
{ "_id" : 3, "make" : "PRS", "description" : "...", "establishedYear" : 1985, "in_stock" : true, "rating" : 9 }
{ "_id" : 2, "make" : "Gibson", "description" : "...", "establishedYear" : 1902, "in_stock" : true, "rating" : 8 }
{ "_id" : 5, "make" : "Ibanez", "description" : "...", "establishedYear" : 1957, "in_stock" : true, "rating" : 7 }

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 guitars collection for documents in which the description field contains the phrase "classic guitars."

var result = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.Phrase(g => g.Description, "classic guitars"))
.ToList();

The search returns the following documents:

{ "_id" : 1, "make" : "Fender", "description" : "Classic guitars known for their versatility.", "establishedYear" : 1946, "in_stock" : true, "rating" : 9 }
{ "_id" : 2, "make" : "Gibson", "description" : "Classic guitars known for their rich, full tones.", "establishedYear" : 1902, "in_stock" : true, "rating" : 8 }

You can also search the collection for documents that match multiple separate phrases as follows:

var result = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.Phrase(g => g.Description, new List<string>() { "classic guitars", "quality guitars" }))
.ToList();

This search returns the following documents:

{ "_id" : 1, "make" : "Fender", "description" : "Classic guitars known for their versatility.", "establishedYear" : 1946, "in_stock" : true, "rating" : 9 }
{ "_id" : 4, "make" : "Kiesel", "description" : "Quality guitars made only for custom orders.", "establishedYear" : 2015, "in_stock" : false, "rating" : null }
{ "_id" : 2, "make" : "Gibson", "description" : "Classic guitars known for their rich, full tones.", "establishedYear" : 1902, "in_stock" : true, "rating" : 8 }

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 guitars collection for documents in which the value of the description field matches each of the following criteria:

  • Contains the string "classic" or the string "quality"

  • Does not contain the string "custom"

var result = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.QueryString(g => g.Description, "(classic OR quality) AND NOT custom"))
.ToList();

The search returns the following documents:

{ "_id" : 1, "make" : "Fender", "description" : "Classic guitars known for their versatility.", "establishedYear" : 1946, "in_stock" : true, "rating" : 9 }
{ "_id" : 3, "make" : "PRS", "description" : "High-end guitars known for their quality.", "establishedYear" : 1985, "in_stock" : true, "rating" : 9 }
{ "_id" : 2, "make" : "Gibson", "description" : "Classic guitars known for their rich, full tones.", "establishedYear" : 1902, "in_stock" : true, "rating" : 8 }

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 guitars collection for all documents with an establishedYear value greater than 1980 and less than 2020.

var result = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.Range(g => g.EstablishedYear, SearchRangeBuilder.Gt(1980).Lt(2020)))
.ToList();

The search returns the following results:

{ "_id" : 3, "make" : "PRS", "description" : "High-end guitars known for their quality.", "establishedYear" : 1985, "in_stock" : true, "rating" : 9 }
{ "_id" : 4, "make" : "Kiesel", "description" : "Quality guitars made only for custom orders.", "establishedYear" : 2015, "in_stock" : false, "rating" : null }
{ "_id" : 6, "make" : "Strandberg", "description" : "Modern guitars known for their headless models.", "establishedYear" : 1982, "in_stock" : false, "rating" : null }

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 guitars collection for documents in which the value of the make field contains exactly six letters.

var regex = "[A-Za-z]{6}";
var result = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.Regex(g => g.Make, regex))
.ToList();

The search returns the following results:

{ "_id" : 1, "make" : "Fender", "description" : "Classic guitars known for their versatility.", "establishedYear" : 1946, "in_stock" : true, "rating" : 9 }
{ "_id" : 2, "make" : "Gibson", "description" : "Classic guitars known for their rich, full tones.", "establishedYear" : 1902, "in_stock" : true, "rating" : 8 }
{ "_id" : 4, "make" : "Kiesel", "description" : "Quality guitars made only for custom orders.", "establishedYear" : 2015, "in_stock" : false, "rating" : null }
{ "_id" : 5, "make" : "Ibanez", "description" : "Well-crafted guitars used by many professional guitarists.", "establishedYear" : 1957, "in_stock" : true, "rating" : 7 }

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 = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.Regex(g => g.Make, regex, 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 guitars collection for documents in which the value of the description field contains the strings "guitars" and "quality" within one word of each other.

var searchTerms = new[]
{
Builders<Guitar>.SearchSpan.Term(g => g.Description, "guitars"),
Builders<Guitar>.SearchSpan.Term(g => g.Description, "quality")
};
var result = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.Span(Builders<Guitar>.SearchSpan.Near(searchTerms, 1)))
.ToList();

The search returns the following document:

{ "_id" : 4, "make" : "Kiesel", "description" : "Quality guitars made only for custom orders.", "establishedYear" : 2015, "in_stock" : false, "rating" : null }

Although the document with _id: 3 contains the strings "guitars" and "quality", they are separated by more than one word, so the search omits this document from the results.

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, Atlas Search also looks for a match for each term in the string separately.

The following example searches the guitars collection for documents in which the value of the description field contains the string "used by professionals".

var result = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.Text(g => g.Description, "used by professional"))
.ToList();

The search returns the following document:

{ "_id" : 5, "make" : "Ibanez", "description" : "Well-crafted guitars used by many professional guitarists.", "establishedYear" : 1957, "in_stock" : true, "rating" : 7 }

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 make field contains the string "Strand" followed by any other characters.

var result = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.Wildcard(g => g.Make, "Strand*"))
.ToList();

The search returns the following document:

{ "_id" : 6, "make" : "Strandberg", "description" : "Modern guitars known for their headless models.", "establishedYear" : 1982, "in_stock" : false, "rating" : null }

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 = guitarsCollection.Aggregate()
.Search(Builders<Guitar>.Search.Wildcard(g => g.Make, "Strand*", 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