Earlz
Earlz

Reputation: 63875

How do I resolve a year/month/day date to a more specific date with time data in MongoDB?

I'm working on converting my blog over to use /year/month/day type URLs. I've ran into a pretty bad problem with the concept though. I want to only have down to hour/minute resolution, but of course all of my entries are stored with a full time specific as possible(and I don't want to change that).

How exactly do I go about resolving a specific date to a less specific date with MongoDB? I'm using 10gen's official MongoDB mapper for .Net.

My data-model looks like:

public class BlogEntryData
{
    [BsonId]
    public ObjectId ID;
    public string Title;
    public string Text;
    public DateTime Posted;
    public DateTime Edited;
    public List<string> Tags;
    [BsonDefaultValue(true)]
    public bool Publish;
}

and I get an entry for my blog using

var c=Config.GetDB().GetCollection<BlogEntryData>("entries");
BlogEntryData entry;
try
{
    entry=c.FindOneByIdAs<BlogEntryData>(new ObjectId(RouteParams["id"]));
}
catch
{
    throw new HttpException(404,"Blog entry not found");
}

if(entry==null)
{
    throw new HttpException(404,"Blog entry not found");
}

I'm know how to change it to use instead of ID something like a numerical search field or whatever, but I've never queried against dates.

Also, as an aside, would it be better to store the "URL date" denormalized as a string in my entry model? I'd only want to do this if indexes didn't work properly on dates or something

Upvotes: 0

Views: 1710

Answers (2)

cirrus
cirrus

Reputation: 5672

your DateTimes can be represented in Mongo with the following syntax;

ISODate("2012-10-11T17:33:51.994Z")

Which is the canonical, sortable format. So it starts with year, then month, then day, then hour etc, so it's already least to most specific order. There's a couple of things you can do with this.

  1. You can do string parsing over it, just using the first part of the string. But that's not too smart.
  2. You can simply duplicate the year and month as separate fields, in addition to the ISODate(). The advantage here is that you can reference those fields directly and you can index them specifically.
  3. Finally, you can search using a range, the shorthand for which can be used thus;

db.so.find({Posted:{$gt: ISODate("2012-10-11"), $lt:ISODate("2012-10-12")}})

I wouldn't recommend 1 at all, but 2 and 3 would work very well.

And incidentally, both those mechanisms would translate well into the C# driver. So by way of a more complete answer;

        var dayOfInterest = new DateTime(2012, 10, 11);
        var rangeOfInterest = dayOfInterest.AddDays(1);

// ...

         var entries = c.FindAs<BlogEntryData>(Query.And(
                                    Query.GT("Posted", dayOfInterest),
                                    Query.LT("Posted", rangeOfInterest)
                         ));

Upvotes: 2

ACE
ACE

Reputation: 484

Before I get started, let me make sure that I understood your question correctly. You are currently storing dates in the Date/Time format, but would like to be able to use and query on the dates in a less finely grained way. If this is what you were wondering, then I have some good news for you: all of this is quite simple in mongodDB.

First of all, you should read the mongodb cookbook post on this topic to learn how to query and index on dates inside of mongodb.

Secondly, once you have the date in c#, it is (I believe, I tried to confirm with some searches but am still not 100% sure) in the c# DateTime class. This class has quite a few methods that can be used to view the date with different granularity. For more info on the subject look at the microsoft documentation

Hopefully this answers your questions and gives you the tools you need to keep on enjoying mongodb

Upvotes: 0

Related Questions