I am trying to use NodaTime in my app. The app persists data in a mongodb database. Consider the following class
public class SomeType
{
public ObjectId Id { get; set; }
public Instant Instant { get; set; }
[BsonDateTimeOptions(Kind = DateTimeKind.Local)]
public DateTime DateTime { get; set; }
[BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
public DateTime DateTimeUtc { get; set; }
// public ZonedDateTime ZonedDateTime { get; set; }
// public LocalDateTime LocalDateTime { get; set; }
}
Without adding a custom serializer, the Instant
property of the class doesn't get stored in the db. Reading the document from the db also fails.
public class InstantBsonSerializer : BsonBaseSerializer
{
public override object Deserialize(BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options)
{
var ticks = bsonReader.ReadInt64();
return new Instant(ticks);
}
public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
{
var ticks = bsonReader.ReadInt64();
return new Instant(ticks);
}
public override void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
{
var instant = (Instant) value;
bsonWriter.WriteInt64(instant.Ticks);
}
}
I created the above serializer and registered it properly. I am now able to save and retrieve instances of my class with the proper value set for Instant
.
My question is how does the C# driver handle searching using linq?
var list = mongoDatabase.GetCollection<SomeType>("SomeType")
.AsQueryable<SomeType>()
.Where(x => x.Instant < Instant.FromDateTimeUtc(dateTime.ToUniversalTime()))
.ToList();
Console.WriteLine(list.Count);
I get the correct list of documents. I am trying to understand HOW mongodb gets this data. Does it first load ALL data, deserialize it properly and then filter? Or does it serialize the Instant
value of the where clause and use the serialized value to filter all documents, load matching ones and then deserialize?
I tried seeing the query logged by the mongodb profiler, but its doesnt seem to log anything. I have set the profiling level to 2.
In the case of Instant
the serialized value is a long
. But in case of ZonedDateTime
, the serialized value will be a document with two properties. How will searching work in that case?
Edit:
I was able to get the profiling to work. The following c# query,
mongoDatabase.GetCollection<SomeType>("SomeTypeCollection")
.AsQueryable<SomeType>()
.Where(x => x.Instant < Instant.FromDateTimeUtc(DateTime.UtcNow))
.ToList();
results in the following mongodb query
{ "Instant": { $lt: 13781017828460782 }}
Meaning, the c# driver serializes my Instant
object and uses the serialized value to filter the results in the db itself.