I am manually serializing a number of POCOs using Newtonsoft JsonTextWriter and saving the result as a MongoDB BsonDocument.
//
// POCO to store in MongoDB
public class Session
{
public DateTime? StartUTCTimestamp { get; set; }
public DateTime? StartTimestamp { get; set; }
public DateTime? EndTimestamp { get; set; }
public void ToJSON(ref JsonTextWriter writer)
{
Session session = this;
writer.WriteStartObject(); // {
writer.WritePropertyName("StartUTCTimestamp");
writer.WriteValue(session.StartUTCTimestamp);
writer.WritePropertyName("StartTimestamp");
writer.WriteValue(session.StartTimestamp);
writer.WritePropertyName("EndTimestamp");
writer.WriteValue(session.EndTimestamp);
writer.WriteEndObject(); // }
}
}
A method in a test application which is used to import the data, retrieves all the Session objects from a SQL Server database (using Telerik's Open Access ORM) storing the results in an List. I serialize each Session by calling the ToJSON() method defined on the POCO (see above), passing in a reference to a JsonTextWriter. The resulting JSON string is then deserialized, using the C# MongoDB driver, into a BsonDocument which is then saved to Mongo. (The example below is from an ASP.NET Web Forms page, hence the alert box user controls).
private void LoadData()
{
DateTime startDate = new DateTime(2015,12,31,23,59,59);
var collection = _database.GetCollection<BsonDocument>("sessions");
using (DbContext ctx = new DbContext())
{
List<Session> sessions = ctx.Sessions.Where().ToList();
foreach (Session item in sessions)
{
JsonTextWriter writer = null;
try
{
StringWriter sw = new StringWriter();
writer = new JsonTextWriter(sw);
writer.CloseOutput = true;
item.ToJSON(ref writer);
String json = sw.ToString();
BsonDocument doc = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>(json);
collection.InsertOne(doc);
this.ucAlertMsg.Show("bg-info", "Completed without exception");
}
catch (Exception ex)
{
while (ex.InnerException != null) { ex = ex.InnerException; }
this.ucAlertMsg.Show("bg-danger", ex.Message);
}
finally
{
writer.Close();
}
}
}
}
This is saving the document just fine, however, I am unable to effectively query the documents, filtering on a date range. I believe, based on several other posts and articles that I have read, that this may be because the value is stored as a string instead of an "ISODate()".
//
// This is what IS saved
{
"_id" : ObjectId("5729128cd9017a248cbe6284"),
"StartUTCTimestamp" : "2015-12-15T23:24:06",
"StartTimestamp" : "2015-12-15T18:24:06",
"EndTimestamp" : "2015-12-15T18:26:59",
}
//
// Is this what I need?
{
"_id" : ObjectId("5729128cd9017a248cbe6284"),
"StartUTCTimestamp" : ISODate("2015-12-15T23:24:06"),
"StartTimestamp" : ISODate("2015-12-15T18:24:06"),
"EndTimestamp" : ISODate("2015-12-15T18:26:59"),
}
In my LoadData() method I have tried a number of configurations on the TextWriter which, according to some of the articles I have read seems like it should have helped ...
StringWriter sw = new StringWriter();
writer = new JsonTextWriter(sw);
writer.DateFormatHandling = DateFormatHandling.IsoDateFormat;
writer.CloseOutput = true;
Assigning the "IsoDateFormat" to the "DateFormatHanding" setting on the writer produced no difference. I also tried "MicrosoftDateFormat" and the data was still stored as a string but the format was different.
The actual question
So that's all the set up ... the question is "how do I search MongoDB documents based on date"?
Using the C# driver for MongoDB allows me to search using Linq. Here's the linq query I am using.
IMongoCollection<Session> collection = database.GetCollection<Session>("sessions");
DateTime startDate = (this.StartDate.HasValue) ? this.StartDate.Value : DateTime.Now.AddDays(-7);
DateTime endDate = (this.EndDate.HasValue) ? this.EndDate.Value : DateTime.Now;
var data = collection.Find<Session>(e => e.StartTimestamp.Value >= startDate && e.StartTimestamp.Value <= endDate).ToList();
Since the JSON maps directly back to a Session POCO I should be able to use that type (?). I can successfully filter on other fields in the Session POCO. It's just the dates that are giving me fits.
I am guessing that there is either something amiss or an oversight in my implementation or that since the data is being stored as a string it's not able to be compared as a Date(?).
Any insight would be greatly appreciated.
Thanks, -G