MongoDB providers two element query operators that helps you find documents based on a field's existence or type. In other words, you can match documents based on whether a field exists or in case it does exist, based on its type. The two element operators presented on this section are:
Operator
Description
Exists
Matches documents when the specified field exists
Type
Matches documents when a field is of the specified type
Exists operator - $exists
The $exists operator matches the documents that contain the specified field, even if its value is null.
The filter definition being created with the Existsmethod on a specific field, matches the documents which contain the field even if its value is null.
The sample uses the Exists operator to find Order documents that have assigned a lot number. The LotNumber is a nullable int property in the Orderclass.
ElementOperators.cs
var collection = database
.GetCollection<Order>(Constants.InvoicesCollection);
// find all orders having a lotnumber
var lotNumberFilter = Builders<Order>.Filter
.Exists(o => o.LotNumber, exists:true);
var ordersWithLotNumber = await collection
.Find(lotNumberFilter).ToListAsync();
var bsonCollection = database
.GetCollection<BsonDocument>(Constants.InvoicesCollection);
var bsonLotNumberFilter = Builders<BsonDocument>.Filter
.Exists("lotNumber", exists: true);
var bsonOrdersWithLotNumber = await collection
.Find(lotNumberFilter).ToListAsync();
public class Order
{
[BsonId]
public int OrderId { get; set; }
public string Item { get; set; }
public int Quantity { get; set; }
[BsonIgnoreIfDefault]
public int? LotNumber { get; set; }
public ShipmentDetails ShipmentDetails { get; set; }
}
LotNumber property has the [BsonIgnoreIfDefault] attribute assigned. This ensures that when a document having null LotNumber is inserted in the collection, this field will be totally ignored, meaning the document will not contain a lotNumber field.
On the contrary, if you omit this attribute and try to insert a document with null LotNumber, the field will be added with a null value as follow.
Use this operator when you need to ensure that a document's field has (or hasn't) been assigned with a specific value type.
The sample uses the Type operator to find all orders that have been shipped by checking that the ShippedDateproperty has been assigned with a DateTime value.
ElementOperators.cs
var collection = database
.GetCollection<User>(Constants.InvoicesCollection);
// find documents with shippedDate assigned a DateTime value
var typeFilter = Builders<Order>.Filter
.Type(o => o.ShipmentDetails.ShippedDate, BsonType.DateTime);
var shippedOrders = await collection
.Find(typeFilter).ToListAsync();
var bsonCollection = database
.GetCollection<BsonDocument>(Constants.InvoicesCollection);
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();
db.invoices
.find({"shipmentDetails.shippedDate" : { $type: 9 }})
db.invoices.find({"shipmentDetails.shippedDate" : { $type: "date" }})
// type 9 is the integer identifier for Date types
// https://docs.mongodb.com/manual/reference/bson-types/
---------------------------
// sample matched document
{
"_id" : 0,
"item" : "Generic Metal Cheese",
"quantity" : 9,
"shipmentDetails" : {
"shippedDate" : ISODate("2019-07-06T01:53:49.804+03:00"), // matched here
"shipAddress" : "7870 Shannon Mills, West Theodoreview, Palau",
"city" : "Swaniawskimouth",
"country" : "Guadeloupe",
"contactName" : "Hermina Boyer",
"contactPhone" : "495-231-3113"
}
}
public class Order
{
[BsonId]
public int OrderId { get; set; }
public string Item { get; set; }
public int Quantity { get; set; }
[BsonIgnoreIfDefault]
public int? LotNumber { get; set; }
public ShipmentDetails ShipmentDetails { get; set; }
}
public class ShipmentDetails
{
[BsonIgnoreIfDefault]
public DateTime? ShippedDate { get; set; }
public string ShipAddress { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string ContactName { get; set; }
public string ContactPhone { get; set; }
}
Query for NULL values
Assuming you have a property that might get assigned with NULLvalue, you can find these documents by applying a filter on BsonType.Null types on that property.
The sample finds all documents with NULL shipment's contact phone number.
ElementOperators.cs
var collection = database
.GetCollection<Order>(Constants.InvoicesCollection);
// search for null contact phone numbers
// the field does exists, but has null value
var nullContactPhoneFilter = Builders<Order>.Filter
.Type(o => o.ShipmentDetails.ContactPhone, BsonType.Null);
var nullContactPhoneOrders = await collection
.Find(nullContactPhoneFilter).ToListAsync();
var bsonCollection = database
.GetCollection<BsonDocument>(Constants.InvoicesCollection);
var bsonNullContactPhoneFilter = Builders<BsonDocument>.Filter
.Type("shipmentDetails.contactPhone", BsonType.Null);
var bsonNullContactPhoneOrders = await bsonCollection
.Find(bsonNullContactPhoneFilter).ToListAsync();
public class Order
{
[BsonId]
public int OrderId { get; set; }
public string Item { get; set; }
public int Quantity { get; set; }
[BsonIgnoreIfDefault]
public int? LotNumber { get; set; }
public ShipmentDetails ShipmentDetails { get; set; }
}
public class ShipmentDetails
{
[BsonIgnoreIfDefault]
public DateTime? ShippedDate { get; set; }
public string ShipAddress { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string ContactName { get; set; }
public string ContactPhone { get; set; }
}
The Typeoperator matches documents where the field's value is an instance of a .