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 IEnumerable<Pet> Pets { get; set; }

    public int[] FavoriteNumbers { get; set; }

    public HashSet<string> FavoriteNames { get; set; }

    public DateTime CreatedAtUtc { 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

```csharp
int[] localAges = new [] { 10, 20, 30 };
Find(p => !localAges.Contains(p.Age));
{ Age: { $nin: [10, 20, 30] } }

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

// no example yet

$nor

// no example yet

Element

See the MongoDB documentation for more information on each operator.

$exists

// no example yet

$type

// no example yet

Evaluation

See the MongoDB documentation for more information on each operator.

$mod

// no example yet

$regex

// no example yet

$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.

$add

p => p.Age + 2;
{ $add: [ '$Age', 2 ] }

$subtract

p => p.Age - 2;
{ $subtract: [ '$Age', 2 ] }

$multiply

p => p.Age * 2;
{ $multiply: [ '$Age', 2 ] }

$divide

p => p.Age / 2;
{ $divide: [ '$Age', 2 ] }

$mod

p => p.Age % 2;
{ $mod: [ '$Age', 2 ] }

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.

$size

p => p.FavoriteNumbers.Length;
{ $size: '$FavoriteNumbers' }

p => p.FavoriteNumbers.Count();
{ $size: '$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' }