Introduction
In this article, we will understand how to use the different filters available in MongoDB.Driver with .NET and C#. The article uses a .NET 8 Web API project and performs the operations directly in the controller instead of introducing a separate service or repository layer.
If you want to see how MongoDB is configured in a .NET project, refer to the previous article, Implementing MongoDB with .NET.
Create the Collection Instance
The controller uses an IMongoCollection<Employee> instance that is created from configuration values.
private readonly IMongoCollection<Employee> _employeeCollection;
public MongoFiltersController(IMongoClient mongoClient, IConfiguration configuration)
{
var databaseName = configuration.GetValue<string>("MongoDbSettings:DatabaseName");
var employeeCollection = configuration.GetValue<string>("MongoDbSettings:Collections:EmployeeCollection");
var database = mongoClient.GetDatabase(databaseName);
_employeeCollection = database.GetCollection<Employee>(employeeCollection);
}The sample employee document uses this model:
public class Employee
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Designation { get; set; }
public decimal Salary { get; set; }
public DateTime DateOfBirth { get; set; }
public string[] Skills { get; set; }
}Equality Filter
[HttpGet("eq")]
public async Task<IActionResult> Equal(string name)
{
var filter = Builders<Employee>.Filter.Eq(emp => emp.Name, name);
var results = await _employeeCollection.Find(filter).ToListAsync();
return Ok(results);
}Use Eq when you need to match an exact field value.
Not Equal Filter
[HttpGet("ne")]
public async Task<IActionResult> NotEqual(string name)
{
var filter = Builders<Employee>.Filter.Ne(emp => emp.Name, name);
var results = await _employeeCollection.Find(filter).ToListAsync();
return Ok(results);
}Use Ne to exclude documents with a matching value.
Greater Than Filter
[HttpGet("gt")]
public async Task<IActionResult> GreaterThan(int age)
{
var filter = Builders<Employee>.Filter.Gt(emp => emp.Age, age);
// var filter = Builders<Employee>.Filter.Gt(emp => emp.DateOfBirth, DateTime.Now);
var results = await _employeeCollection.Find(filter).ToListAsync();
return Ok(results);
}Use Gt for numeric or date values that must be greater than the provided value.
Greater Than or Equal Filter
[HttpGet("gte")]
public async Task<IActionResult> GreaterThanOrEqual(int age)
{
var filter = Builders<Employee>.Filter.Gte(emp => emp.Age, age);
// var filter = Builders<Employee>.Filter.Gte(emp => emp.DateOfBirth, DateTime.Now);
var results = await _employeeCollection.Find(filter).ToListAsync();
return Ok(results);
}Use Gte to include values equal to the target as well.
Less Than Filter
[HttpGet("lt")]
public async Task<IActionResult> LessThan(int age)
{
var filter = Builders<Employee>.Filter.Lt(emp => emp.Age, age);
// var filter = Builders<Employee>.Filter.Lt(emp => emp.DateOfBirth, DateTime.Now);
var results = await _employeeCollection.Find(filter).ToListAsync();
return Ok(results);
}Use Lt for values below the given threshold.
Less Than or Equal Filter
[HttpGet("lte")]
public async Task<IActionResult> LessThanOrEqual(int age)
{
var filter = Builders<Employee>.Filter.Lte(emp => emp.Age, age);
// var filter = Builders<Employee>.Filter.Lte(emp => emp.DateOfBirth, DateTime.Now);
var results = await _employeeCollection.Find(filter).ToListAsync();
return Ok(results);
}Use Lte to include values equal to the target.
In Filter
[HttpGet("in")]
public async Task<IActionResult> In([FromQuery] string[] names)
{
var filter = Builders<Employee>.Filter.In(emp => emp.Name, names);
var results = await _employeeCollection.Find(filter).ToListAsync();
return Ok(results);
}Use In when a field can match any value from a list.
Not In Filter
[HttpGet("nin")]
public async Task<IActionResult> NotIn([FromQuery] string[] names)
{
var filter = Builders<Employee>.Filter.Nin(emp => emp.Name, names);
var results = await _employeeCollection.Find(filter).ToListAsync();
return Ok(results);
}Use Nin to exclude documents that match any value in the list.
And Filter
[HttpGet("and")]
public async Task<IActionResult> And(string name, int age)
{
var filter = Builders<Employee>.Filter.And(
Builders<Employee>.Filter.Eq(emp => emp.Name, name),
Builders<Employee>.Filter.Eq(emp => emp.Age, age));
var results = await _employeeCollection.Find(filter).ToListAsync();
return Ok(results);
}Use And when every condition must be true.
Or Filter
[HttpGet("or")]
public async Task<IActionResult> Or(string name, int age)
{
var filter = Builders<Employee>.Filter.Or(
Builders<Employee>.Filter.Eq(emp => emp.Name, name),
Builders<Employee>.Filter.Eq(emp => emp.Age, age));
var results = await _employeeCollection.Find(filter).ToListAsync();
return Ok(results);
}Use Or when any one of the conditions can match.
Exists Filter
[HttpGet("exists")]
public async Task<IActionResult> Exists(string fieldName)
{
var filter = Builders<Employee>.Filter.Exists(fieldName);
// or
// var filter = Builders<Employee>.Filter.Exists(x => x.Designation);
var results = await _employeeCollection.Find(filter).ToListAsync();
return Ok(results);
}Use Exists to find documents where a field is present.
Type Filter
[HttpGet("type")]
public async Task<IActionResult> Type(string fieldName, BsonType bsonType)
{
var filter = Builders<Employee>.Filter.Type(fieldName, bsonType);
var results = await _employeeCollection.Find(filter).ToListAsync();
return Ok(results);
}Use Type to match the BSON type of a field.
Regular Expression Filter
[HttpGet("regex")]
public async Task<IActionResult> Regex()
{
var pattern = "^J"; // Names starting with 'J'
// var pattern = "n$"; // Names ending with 'n'
// var pattern = ".[aei]."; // Names containing 'a', 'e', or 'i'
var filter = Builders<Employee>.Filter.Regex(emp => emp.Name, new BsonRegularExpression(pattern));
var results = await _employeeCollection.Find(filter).ToListAsync();
return Ok(results);
}Use Regex for pattern-based string matching.
All Filter
[HttpGet("all")]
public async Task<IActionResult> All([FromQuery] string[] skills)
{
var filter = Builders<Employee>.Filter.All(emp => emp.Skills, skills);
var results = await _employeeCollection.Find(filter).ToListAsync();
return Ok(results);
}Use All when an array field must contain every value from the provided list.
ElemMatch Filter
[HttpGet("elemMatch")]
public async Task<IActionResult> ElemMatch(string skill)
{
var filter = Builders<Employee>.Filter.ElemMatch(emp => emp.Skills, skill);
var results = await _employeeCollection.Find(filter).ToListAsync();
return Ok(results);
}Use ElemMatch when at least one array element must satisfy a condition.
Size Filter
[HttpGet("size")]
public async Task<IActionResult> Size(int size)
{
var filter = Builders<Employee>.Filter.Size(emp => emp.Skills, size);
var results = await _employeeCollection.Find(filter).ToListAsync();
return Ok(results);
}Use Size to match the exact number of items in an array field.
Conclusion
In this article, we explored a range of MongoDB filters available in MongoDB.Driver using .NET and C#. These filters make it easy to build precise queries for different types of fields and collections.
The original article also links to the source code on GitHub.
.png)