Logical operators allow you to match documents based on the boolean result coming from a set of expressions. The logical expressions are evaluated for each document in your filter and if their boolean result matches the expected one (true or false) are included or excluded respectively in the returned result. The section contains samples for the following operators:
Operator
Description
AND
Matches documents that fulfill all specified conditions
NOT
Matches documents that don't fulfill the specified expression
OR
Matches documents that fulfill at least one of a set of conditions
NOR
Matches documents that fail to fulfill both conditions
AND operator - $and
The AND operator performs a logical AND on a set of expressions and match documents that satisfy all of them.
Create as many filter definitions you want and pass them as an argument to the AndFilterDefinitionBuilder method.
The sample uses an And operator to find all documents that have male genderAND have the profession field equal to "Doctor".
LogicalOperators.cs
var collection = database
.GetCollection<User>(Constants.UsersCollection);
// create an equality filter on the gender for 'male' (0)
var maleFilter = Builders<User>.Filter
.Eq(u => u.Gender, Gender.Male);
// create an equality filter on profession for 'Doctor'
var doctorFilter = Builders<User>.Filter
.Eq(u => u.Profession, "Doctor");
// compine the filters with AND operator
var maleDoctorsFilter = Builders<User>.Filter
.And(maleFilter, doctorFilter);
var maleDoctors = await collection.Find(maleDoctorsFilter).ToListAsync();
var bsonCollection = database
.GetCollection<BsonDocument>(Constants.UsersCollection);
var bsonMaleFilter = Builders<BsonDocument>.Filter
.Eq("gender", Gender.Male);
var bsonDoctorFilter = Builders<BsonDocument>.Filter
.Eq("profession", "Doctor");
var bsonMaleDoctorsFilter = Builders<BsonDocument>.Filter
.And(bsonMaleFilter, bsonDoctorFilter);
var bsonMaleDoctors = await bsonCollection
.Find(bsonMaleDoctorsFilter).ToListAsync();
public class User
{
[BsonId]
[BsonIgnoreIfDefault] // required for replace documents
public ObjectId Id { get; set; }
public Gender Gender { get; set; }
public string FirstName {get; set; }
public string LastName {get; set; }
public string UserName {get; set; }
public string Avatar {get; set; }
public string Email {get; set; }
public DateTime DateOfBirth {get; set; }
public AddressCard Address {get; set; }
public string Phone {get; set; }
[BsonIgnoreIfDefault]
public string Website {get; set; }
public CompanyCard Company {get; set; }
public decimal Salary { get; set; }
public int MonthlyExpenses { get; set; }
public List<string> FavoriteSports { get; set; }
public string Profession { get; set; }
}
You can combine as many filters as you want to an AND operator. The following sample finds all documents that match the following criteria:
public class User
{
[BsonId]
[BsonIgnoreIfDefault] // required for replace documents
public ObjectId Id { get; set; }
public Gender Gender { get; set; }
public string FirstName {get; set; }
public string LastName {get; set; }
public string UserName {get; set; }
public string Avatar {get; set; }
public string Email {get; set; }
public DateTime DateOfBirth {get; set; }
public AddressCard Address {get; set; }
public string Phone {get; set; }
[BsonIgnoreIfDefault]
public string Website {get; set; }
public CompanyCard Company {get; set; }
public decimal Salary { get; set; }
public int MonthlyExpenses { get; set; }
public List<string> FavoriteSports { get; set; }
public string Profession { get; set; }
}
The inner filter definitions passed as arguments in the And method can be as complex as you want to.
NOT operator - $ne
The NOT operator performs a logical NOT on an expression and match documents that don't satisfy the expression.
Create a filter definition and pass it as an argument to the NotFilterDefinitionBuilder method. The boolean expression's result for the matched documents will be false, meaning that they don't satisfy the expression.
The sample uses an Not operator to find all documents having male gender, which can be translated as NOT female.
LogicalOperators.cs
var collection = database
.GetCollection<User>(Constants.UsersCollection);
// Negates the internal equality filter
var notMaleFilter = Builders<User>.Filter.Not(
// equality filter on gender for Male
Builders<User>.Filter.Eq(u => u.Gender, Gender.Male)
);
var femaleUsers = await collection.Find(notMaleFilter).ToListAsync();
var bsonCollection = database
.GetCollection<BsonDocument>(Constants.UsersCollection);
var bsonNotMaleFilter = Builders<BsonDocument>.Filter
.Not(
Builders<BsonDocument>.Filter.Eq("gender", Gender.Male)
);
var bsonFemaleUsers = await bsonCollection
.Find(bsonNotMaleFilter).ToListAsync();
public class User
{
[BsonId]
[BsonIgnoreIfDefault] // required for replace documents
public ObjectId Id { get; set; }
public Gender Gender { get; set; }
public string FirstName {get; set; }
public string LastName {get; set; }
public string UserName {get; set; }
public string Avatar {get; set; }
public string Email {get; set; }
public DateTime DateOfBirth {get; set; }
public AddressCard Address {get; set; }
public string Phone {get; set; }
[BsonIgnoreIfDefault]
public string Website {get; set; }
public CompanyCard Company {get; set; }
public decimal Salary { get; set; }
public int MonthlyExpenses { get; set; }
public List<string> FavoriteSports { get; set; }
public string Profession { get; set; }
}
OR operator - $or
The OR operator performs a logical OR on an set of expressions and matches documents that satisfy at least on of the expressions.
Create as many filter definitions you want and pass them as an argument to the OrFilterDefinitionBuilder method. The filters passed as parameters can be as complex as you want.
The sample uses an Or operator to find all documents having salary, either too low (less than 1500) or too high ( greater than 4000).
LogicalOperators.cs
var collection = database.GetCollection<User>(Constants.UsersCollection);
// users with salary either < 1500 (too low) or > 4000 (too high)
var orSalaryFilter = Builders<User>.Filter.Or(
Builders<User>.Filter.Lt(u => u.Salary, 1500), // 1st expression
Builders<User>.Filter.Gt(u => u.Salary, 4000) // 2nd expression
);
var lowOrHighSalaryUsers = await collection
.Find(orSalaryFilter).ToListAsync();
var bsonCollection = database
.GetCollection<BsonDocument>(Constants.UsersCollection);
var bsonOrSalaryFilter = Builders<BsonDocument>.Filter.Or(
Builders<BsonDocument>.Filter.Lt("salary", 1500),
Builders<BsonDocument>.Filter.Gt("salary", 4000)
);
var bsonLowOrHighSalaryUsers = await bsonCollection
.Find(bsonOrSalaryFilter).ToListAsync();
public class User
{
[BsonId]
[BsonIgnoreIfDefault] // required for replace documents
public ObjectId Id { get; set; }
public Gender Gender { get; set; }
public string FirstName {get; set; }
public string LastName {get; set; }
public string UserName {get; set; }
public string Avatar {get; set; }
public string Email {get; set; }
public DateTime DateOfBirth {get; set; }
public AddressCard Address {get; set; }
public string Phone {get; set; }
[BsonIgnoreIfDefault]
public string Website {get; set; }
public CompanyCard Company {get; set; }
public decimal Salary { get; set; }
public int MonthlyExpenses { get; set; }
public List<string> FavoriteSports { get; set; }
public string Profession { get; set; }
}
NOR operator - $nor
Create as many filter definitions you want to fail and pass them as an argument to the AndFilterDefinitionBuilder method. The filters passed as parameters can be as complex as you want.
The sample finds documents that fail to satisfy the following criteria:
Have profession equal to "Doctor"
Have salary less than 4500
Since the matched documents needs to fail the above criteria, you should use their negates with an AND operator.
public class User
{
[BsonId]
[BsonIgnoreIfDefault] // required for replace documents
public ObjectId Id { get; set; }
public Gender Gender { get; set; }
public string FirstName {get; set; }
public string LastName {get; set; }
public string UserName {get; set; }
public string Avatar {get; set; }
public string Email {get; set; }
public DateTime DateOfBirth {get; set; }
public AddressCard Address {get; set; }
public string Phone {get; set; }
[BsonIgnoreIfDefault]
public string Website {get; set; }
public CompanyCard Company {get; set; }
public decimal Salary { get; set; }
public int MonthlyExpenses { get; set; }
public List<string> FavoriteSports { get; set; }
public string Profession { get; set; }
}
var collection = database.GetCollection<User>(Constants.UsersCollection);
var firstFilterToFail = Builders<User>.Filter
.Eq(u => u.Profession, "Doctor");
var secondFilterToFail = Builders<User>.Filter
.Lt(u => u.Salary, 4500);
var extensionNorFilter = Builders<User>.Filter
.Nor(firstFilterToFail, secondFilterToFail);
Extensions.cs
public static FilterDefinition<T> Nor<T>(
this FilterDefinitionBuilder<T> builder,
params FilterDefinition<T>[] filters)
{
return builder.And(
filters.Select(builder.Not)
);
}
The Gender property on the User class is an Enum type and the driver is smart enough to translate it properly when sending the query to MongoDB
They have gender Female
They are either "Teacher", Nurse" or "Dentist"
Their salary is between 2000 AND 3200
The NOR operator performs a logical NOR on an set of expressions and matches documents that fail to satisfy all the expressions. Despite the fact that MongoDB supports the operator, you won't find any method on the C# driver. That's totally fine though because you can built it using the AND operator and negating the internal filters.
Of course you can build a simple extension method that does this for you and makes things a little bit easier.