- Reference
- Driver
- Definitions and Builders
- Expressions
Expressions
Many methods in the driver accept expressions as an argument.
For the rest of this page, we’ll use the following class:
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Dictionary<string, Person> Children { get; set; }
public IEnumerable<Pet> Pets { get; set; }
public int[] FavoriteNumbers { get; set; }
public HashSet<string> FavoriteNames { get; set; }
public DateTime CreatedAtUtc { get; set; }
public int PermissionFlags { get; set; }
}
class Pet
{
public string Name { get; set; }
}
Filters
We’ll walk through the supported expressions below. The tests are also a good reference.
Comparison
See the MongoDB documentation for more information on each operator.
$eq
Find(p => p.Name == "Jack")
becomes:
{ Name: 'Jack' }
Note
This is the short form for equality. Depending on context, this might generate{ Name: { $eq: 'Jack' } }
.
$gt
Find(p => p.Age > 10);
{ Age: { $gt: 10 } }
$gte
Find(p => p.Age >= 10);
{ Age: { $gte: 10 } }
$lt
Find(p => p.Age < 10);
{ Age: { $lt: 10 } }
$lte
Find(p => p.Age <= 10);
{ Age: { $lte: 10 } }
$ne
Find(p => p.Age != 10);
{ Age: { $ne: 10 } }
$in
int[] localAges = new [] { 10, 20, 30 };
Find(p => localAges.Contains(p.Age));
{ Age: { $in: [10, 20, 30] } }
int[] localNames = new [] { "Fluffy", "Scruffy" };
Find(p => p.Pets.Any(i => localNames.Contains(i.Name));
{ "Pets.Name": { $in: ["Fluffy", "Scruffy"] } }
int[] localNumbers = new [] { 30, 40 };
Find(p => localNumbers.Any(i => p.FavoriteNumbers.Contains(i));
{ FavoriteNumbers: { $in: [30, 40] } }
$nin
int[] localAges = new [] { 10, 20, 30 };
Find(p => !localAges.Contains(p.Age));
{ Age: { $nin: [10, 20, 30] } }
$bitsAllClear
Find(p => (p.PermissionFlags & 7) == 0);
{ PermissionFlags: { $bitsAllClear: 7 } }
$bitsAllSet
Find(p => (p.PermissionFlags & 7) == 7);
{ PermissionFlags: { $bitsAllSet: 7 } }
$bitsAnyClear
Find(p => (p.PermissionFlags & 7) != 7);
{ PermissionFlags: { $bitsAnyClear: 7 } }
$bitsAnySet
Find(p => (p.PermissionFlags & 7) != 0);
{ PermissionFlags: { $bitsAnySet: 7 } }
Logical
See the MongoDB documentation for more information on each operator.
$or
Find(p => p.Name == "Jack" || p.Age == 10);
{ $or: [{ Name: 'Jack' }, { Age: 10 }] }
$and
Find(p => p.Name == "Jack" && p.Age < 40);
{ Name: 'Jack', Age: { $lt: 40 } }
Find(p => p.Age > 30 && p.Age < 40);
{ Age: { $gt: 30, $lt: 40 }
Find(p => p.Name != "Jack" && p.Name != "Jim");
{ $and: [{ Name: { $ne: 'Jack' } }, { Name: { $ne: 'Jim' } }] }
$not
Find(p => !(p.Age < 18))
{ Age: { $not: { $lt: 18 } } }
$nor
Find(p => !(p.Age < 18 || p.Age >= 65))
{ $nor: [{ Age: { $lt: 18 } }, { Age: { $gte: 65 } }] }
Element
See the MongoDB documentation for more information on each operator.
$exists
Find(p => p.Children.ContainsKey("John"))
{ "Children.John": { $exists: true } }
$type
Find(Builders<Person>.Filter.Type(p => p.Name, BsonType.String))
{ "Name" : { "$type" : 2 } }
Evaluation
See the MongoDB documentation for more information on each operator.
$mod
Find(p => p.Age % 2 == 0)
{ Age: { $mod: [NumberLong(2), NumberLong(0)] } }
$regex
Find(p => p.Name[0] == 'a')
{ Name: /^.{0}a/s }
Find(p => p.Name.Length >= 5)
{ Name: /^.{5,}$/s }
Find(p => p.Name.ToLower() == "john")
{ Name: /^john$/i }
Note
ToLowerInvariant
, ToUpper
, and ToUpperInvariant
are also supported.
Find(p => p.Name.Contains("John"))
{ Name: /John/s }
Note
StartsWith
and EndsWith
are also supported.
Find(p => p.Name.ToLower().Contains("John"))
{ Name: /John/is }
Note
ToLowerInvariant
, ToUpper
, ToUpperInvariant
, Trim
, TrimStart
, and TrimEnd
are also supported for the first function call. StartsWith
and EndsWith
are also supported for the second function call.
$text
// no example yet
$where
// no example yet
Geospatial
See the MongoDB documentation for more information on each operator.
$geoWithin
// no example yet
$geoIntersects
// no example yet
$near
// no example yet
$nearSphere
// no example yet
Array
See the MongoDB documentation for more information on each operator.
$all
var local = new [] { 10, 20 };
Find(x => local.All(i => FavoriteNumbers.Contains(i));
{ FavoriteNumbers: { $all: [10, 20] } }
$elemMatch
Find(x => x.Pets.Any(p => p.Name == "Fluffy" && p.Age > 21);
{ Pets: { $elemMatch: { Name: 'Fluffy', Age: { $gt: 21 } } } }
Find(x => x.FavoriteNumbers.Any(n => n < 42 && n > 21));
{ FavoriteNumbers: { $elemMatch: { $lt: 42, $gt: 21 } } }
Note
Depending on the complexity and the operators involved in the Any method call, the driver might eliminate the $elemMatch
completely. For instance,
Find(x => x.Pets.Any(p => p.Name == "Fluffy"))
{ Pets: { Name: "Fluffy" } }
$size
Find(x => x.FavoriteNumbers.Length == 3);
{ FavoriteNumbers: { $size: 3 } }
Find(x => x.FavoriteNumbers.Length != 3);
{ FavoriteNumbers: { $not: { $size: 3 } } }
Find(x => x.FavoriteNumbers.Any());
{ FavoriteNumbers: { $ne: null, $not: { $size: 0 } } }
Find(x => x.FavoriteNumbers.Count() == 3);
{ FavoriteNumbers: { $size: 3 } }
Aggregation Projections
We’ll walk through the supported expressions below. The tests are also a good reference.
Boolean Expressions
See the MongoDB documentation for more information on each operator.
$and
p => p.Name == "Jack" && p.Age < 40
{ $and: [{ $eq: ['$Name', 'Jack'] }, { $lt: ['$Age', 40] }] }
$or
p => p.Name == "Jack" || p.Age < 40
{ $or: [{ $eq: ['$Name', 'Jack'] }, { $lt: ['$Age', 40] }] }
$not
p => !(p.Name == "Jack")
{ $not: [{ $eq: ['$Name', 'Jack'] }]] }
Set Expressions
See the MongoDB documentation for more information on each operator.
$setEquals
p => p.FavoriteNames.SetEquals(new [] { "Jack", "Jane" });
{ $setEquals: ['$FavoriteNames', [ 'Jack', 'Jane'] ] }
var localSet = new HashSet<int>(new [] { 1, 3, 5 });
p => localSet.SetEquals(p.FavoriteNumbers);
{ $setEquals: [ [1, 3, 5], '$FavoriteNumbers' ] }
$setIntersection
p => p.FavoriteNumbers.Intersect(new [] { 1, 3 });
{ $setIntersection: [ '$FavoriteNumbers', [ 1, 3 ] ] }
p => new [] { 1, 3 }.Intersect(p.FavoriteNumbers);
{ $setIntersection: [ [ 1, 3 ], '$FavoriteNumbers' ] }
$setUnion
p => p.FavoriteNumbers.Union(new [] { 1, 3 });
{ $setUnion: [ '$FavoriteNumbers', [ 1, 3 ] ] }
p => new [] { 1, 3 }.Union(p.FavoriteNumbers);
{ $setUnion: [ [ 1, 3 ], '$FavoriteNumbers' ] }
$setDifference
p => p.FavoriteNumbers.Except(new [] { 1, 3 });
{ $setDifference: [ '$FavoriteNumbers', [ 1, 3 ] ] }
p => new [] { 1, 3 }.Except(p.FavoriteNumbers);
{ $setDifference: [ [ 1, 3 ], '$FavoriteNumbers' ] }
$setIsSubset
p => p.FavoriteNames.IsSubsetOf(new [] { "Jack", "Jane" });
{ $setIsSubset: ['$FavoriteNames', [ 'Jack', 'Jane'] ] }
var localSet = new HashSet<int>(new [] { 1, 3, 5 });
p => localSet.IsSubsetOf(p.FavoriteNumbers);
{ $setIsSubset: [ [1, 3, 5], '$FavoriteNumbers' ] }
$anyElementTrue
p => p.FavoriteNumbers.Any(x => x > 20);
{ $anyElementTrue: { $map: { input: '$FavoriteNumbers', as: 'x', in: { $gt: [ '$$x', 20 ] } } } }
$allElementsTrue
p => p.FavoriteNumbers.All(x => x > 20);
{ $allElementsTrue: { $map: { input: '$FavoriteNumbers', as: 'x', in: { $gt: [ '$$x', 20 ] } } } }
Comparison Expressions
See the MongoDB documentation for more information on each operator.
$cmp
p => p.Name.CompareTo("Jimmy");
{ $cmp: [ '$Name', 'Jimmy' ] }
$eq
p => p.Name == "Jimmy";
{ $eq: [ '$Name', 'Jimmy' ] }
$gt
p => p.Age > 20;
{ $gt: [ '$Age', 20 ] }
$gte
p => p.Age >= 20;
{ $gte: [ '$Age', 20 ] }
$lt
p => p.Age < 20;
{ $lt: [ '$Age', 20 ] }
$lte
p => p.Age <= 20;
{ $lte: [ '$Age', 20 ] }
$ne
p => p.Age != 20;
{ $ne: [ '$Age', 20 ] }
Arithmetic Expressions
See the MongoDB documentation for more information on each operator.
$abs
p => Math.Abs(p.Age);
{ $abs: "$Age" }
$add
p => p.Age + 2;
{ $add: [ '$Age', 2 ] }
$ceil
p => Math.Ceiling(p.Age);
{ $ceil: "$Age" }
$divide
p => p.Age / 2;
{ $divide: [ '$Age', 2 ] }
$exp
p => Math.Exp(p.Age);
{ $exp: ["$Age"] }
$floor
p => Math.Floor(p.Age);
{ $floor: "$Age" }
$ln
p => Math.Log(p.Age);
{ $ln: ["$Age"] }
$log
p => Math.Log(p.Age, 10);
{ $log: ["$Age", 10] }
$log10
p => Math.Log10(p.Age);
{ $log10: ["$Age"] }
$mod
p => p.Age % 2;
{ $mod: [ '$Age', 2 ] }
$multiply
p => p.Age * 2;
{ $multiply: [ '$Age', 2 ] }
$pow
p => Math.Pow(p.Age, 10);
{ $pow: ["$Age", 10] }
$sqrt
p => Math.Sqrt(p.Age);
{ $sqrt: ["$Age"] }
$subtract
p => p.Age - 2;
{ $subtract: [ '$Age', 2 ] }
$trunc
p => Math.Truncate(p.Age);
{ $trunc: "$Age" }
String Expressions
See the MongoDB documentation for more information on each operator.
$concat
p => p.Name + "Awesome";
{ $concat: [ '$Name', 'Awesome' ] }
$substr
p => p.Name.Substring(3, 20)
{ $substr: [ '$Name', 3, 20 ] }
$toLower
p => p.Name.ToLower()
{ $toLower: '$Name' }
$toUpper
p => p.Name.ToUpper()
{ $toUpper: '$Name' }
$strcasecmp
You must use StringComparison.OrdinalIgnoreCase
for this method.
p => p.Name.Equals("balloon", StringComparison.OrdinalIgnoreCase);
{ $strcasecmp: ['$Name', 'balloon' ] }
Text Search Expressions
See the MongoDB documentation for more information on each operator.
$meta
// no example yet
Array Expressions
See the MongoDB documentation for more information on each operator.
$arrayElemAt
p => p.FavoriteNumbers.First()
{ $arrayElemAt: ['$FavoriteNumbers', 0] }
p => p.FavoriteNumbers.Last()
{ $arrayElemAt: ['$FavoriteNumbers', -1] }
$avg
p => p.FavoriteNumbers.Average()
{ $avg: '$FavoriteNumbers' }
$concatArrays
p => p.FavoriteNumbers.Concat(new [] { 1, 2, 3 })
{ $concatArrays: ['$FavoriteNumbers', [1, 2, 3]] }
$filter
p => p.FavoriteNumbers.Where(x => x > 10)
{ $filter: { input: '$FavoriteNumbers', as: 'x', cond: { $gt: ['$$x', 10] } } }
$map
p => p.FavoriteNumbers.Select(x => x + 10)
{ $map: { input: '$FavoriteNumbers', as: 'x', in: { $add: ['$$x', 10] } } }
$max
p => p.FavoriteNumbers.Max()
{ $max: '$FavoriteNumbers' }
$min
p => p.FavoriteNumbers.Min()
{ $min: '$FavoriteNumbers' }
$size
p => p.FavoriteNumbers.Length;
{ $size: '$FavoriteNumbers' }
p => p.FavoriteNumbers.Count();
{ $size: '$FavoriteNumbers' }
$slice
p => p.FavoriteNumbers.Take(2)
{ $slice: ['$FavoriteNumbers', 2] }
p => p.FavoriteNumbers.Skip(3).Take(2)
{ $slice: ['$FavoriteNumbers', 3, 2] }
$stdDevPop
p => p.FavoriteNumbers.StandardDeviationPopulation()
{ $stdDevPop: '$FavoriteNumbers' }
$stdDevSamp
p => p.FavoriteNumbers.StandardDeviationSample()
{ $stdDevPop: '$FavoriteNumbers' }
$sum
p => p.FavoriteNumbers.Sum()
{ $sum: '$FavoriteNumbers' }
Variable Expressions
See the MongoDB documentation for more information on each operator.
$map
p => p.Pets.Select(x => x.Name + " is awesome");
{ $map: { input: '$Name', as: 'x', in: { $concat: [ '$$x', ' is awesome' ] } } }
$let
// no example yet
Literal Expressions
See the MongoDB documentation for more information on each operator.
$literal
The only time $literal
will be used from the driver is if the constant starts with a $
.
p => p.Name == "$1");
{ $eq: [ '$Name', { $literal: '$1' } ] }
Date Expressions
See the MongoDB documentation for more information on each operator.
$dayOfYear
p => p.CreatedAtUtc.DayOfYear);
{ $dayOfYear: '$CreatedAtUtc' }
$dayOfMonth
p => p.CreatedAtUtc.Day);
{ $dayOfMonth: '$CreatedAtUtc' }
$dayOfWeek
The .NET constant for day of week is 1 less than that in MongoDB. As such, we must subtract 1 from the MongoDB version in order for mapping back to the .NET type to be accurate.
p => p.CreatedAtUtc.DayOfWeek;
{ $subtract: [ { $dayOfWeek: '$CreatedAtUtc' }, 1 ] }
$year
p => p.CreatedAtUtc.Year;
{ $year: '$CreatedAtUtc' }
$month
p => p.CreatedAtUtc.Month;
{ $month: '$CreatedAtUtc' }
$week
// no example yet
$hour
p => p.CreatedAtUtc.Hour;
{ $hour: '$CreatedAtUtc' }
$minute
p => p.CreatedAtUtc.Minute;
{ $minute: '$CreatedAtUtc' }
$second
p => p.CreatedAtUtc.Second;
{ $second: '$CreatedAtUtc' }
$millisecond
p => p.CreatedAtUtc.Millisecond;
{ $millisecond: '$CreatedAtUtc' }
$dateToString
// no example yet
Conditional Expressions
See the MongoDB documentation for more information on each operator.
$cond
p => p.Name == "Jack" ? "a" : "b";
{ $cond: [ { $eq: [ '$Name', 'Jack' ] }, 'a', 'b' ] }
$ifNull
p => p.Name ?? "awesome";
{ $ifNull: [ '$Name', 'awesome' ] }
Accumulators
See the MongoDB documentation for more information on each operator.
Also, the tests are a good reference.
Note
These are only supported in a grouping expression.In the examples below, it should be assumed that g
is of type IGrouping<TKey, TElement>
.
$sum
g => g.Sum(x => x.Age);
{ $sum: '$Age' }
g => g.Count()
{ $sum: 1 }
$avg
g => g.Average(x => x.Age);
{ $avg: '$Age' }
$first
g => g.First().Age);
{ $first: '$Age' }
$last
g => g.Last().Age);
{ $last: '$Age' }
$max
g => g.Max(x => x.Age);
{ $max: '$Age' }
$min
g => g.Min(x => x.Age);
{ $min: '$Age' }
$push
g => g.Select(p => p.Name)
{ $push: '$Name' }
g => g.Select(p => p.Name).ToArray()
{ $push: '$Name' }
g => g.Select(p => p.Name).ToList()
{ $push: '$Name' }
$addToSet
g => new HashSet<string>(g.Select(p => p.Name));
{ $addToSet: '$Name' }
g => g.Select(p => p.Name).Distinct();
{ $addToSet: '$Name' }