craiggwilson / fluent-mongo

Provides a fluent interface on top of the 10gen driver including Linq.
172 stars 28 forks source link

DateTime support #37

Closed Fristi closed 12 years ago

Fristi commented 13 years ago

Currently it's not possible to query on date:

from n in queryable where n.DateTime.Year == 1970 select n

Thows an exception:

System.NotSupportedException : The member Year is not supported.
at FluentMongo.Linq.Translators.JavascriptFormatter.VisitMemberAccess(MemberExpression m)
at FluentMongo.Linq.Expressions.ExpressionVisitor.Visit(Expression exp)
at FluentMongo.Linq.Translators.JavascriptFormatter.VisitBinary(BinaryExpression b)
at FluentMongo.Linq.Expressions.ExpressionVisitor.Visit(Expression exp)
at FluentMongo.Linq.Translators.JavascriptFormatter.FormatJavascript(Expression expression)
at FluentMongo.Linq.Translators.MongoQueryObjectBuilder.VisitSelect(SelectExpression select)
at FluentMongo.Linq.Translators.MongoQueryObjectBuilder.VisitProjection(ProjectionExpression projection)
at FluentMongo.Linq.Translators.MongoQueryObjectBuilder.Build(Expression expression)
at FluentMongo.Linq.ExecutionBuilder.VisitProjection(ProjectionExpression projection)
at FluentMongo.Linq.MongoQueryProvider.Execute(Expression expression)
at FluentMongo.Linq.MongoQueryProvider.Execute(Expression expression)
at System.Linq.Queryable.Count(IQueryable`1 source)

http://cookbook.mongodb.org/patterns/date_range/

Would this be hard to implement ? I can help out if you give me some pointers :)

craiggwilson commented 13 years ago

I don't think this is possible in a query out of the box. What would this syntax look in the native mongodb query language?

Fristi commented 13 years ago

var query = Query.And( 
    Query.GT("LastActivityDate", compareTime), 
    Query.EQ("ApplicationName", applicationName) 
); 
var json = query.ToJson(); 
The value of json will be: 
{ "LastActivityDate" : { "$gt" : ISODate("2011-08-11T10:45:00Z") }, 
"ApplicationName" : "A" } 

from: http://groups.google.com/group/mongodb-csharp/browse_thread/thread/7cf046093eebcbd4

Where compareTime is DateTime.

You would need to implement some smart specification pattern to build queries for specific date parts like years, months,etc

Like filtering on the Year 1970 would result in something like:

{DateTime: {$gte: ISODate("1970-01-01T00:00:00Z"), $lt: ISODate("1971-01-01T00:00:00Z")}}

http://cookbook.mongodb.org/patterns/date_range/

If you read the comments of the cookbook:

This is not a solution, it finds documents only for one year. What if I want to select all users born in September, withour specifying the year.

Response from dmerriman (one of the mongodb devs) responded this one month ago:

an $operator will be added for that in the future. for now you'd have to use map/reduce or $where or explicitly store the month.

craiggwilson commented 13 years ago

So, my suggestion would be the same as dwight's. Don't store your dates as dates. Rather, store them in their parts so you can query on them. It seems like this would be a half solution because the only thing we could do here would be year. In addition, it seems like this query would be easy enough to generate without specifying the year.

You are welcome to put this in if you want... The file you would need to modify would be this one: https://github.com/craiggwilson/fluent-mongo/blob/master/src/FluentMongo/Linq/Translators/BsonDocumentFormatter.cs.