views:

84

answers:

3

I need to create a named scope in Mongoid that compares two Time fields within the same document. Such as

scope :foo, :where => {:updated_at.gt => :checked_at}

This obviously won't work as it treats :checked_at as a symbol, not the actual field. Any suggestions on how this can be done?

Update 1

Here is my model where I have this scope declared, with a lot of extra code stripped out.

class User
  include Mongoid::Document
  include Mongoid::Paranoia
  include Mongoid::Timestamps

  field :checked_at, :type => Time

  scope :unresolved, :where => { :updated_at.gt => self.checked_at }
end

This gives me the following error:

'<class:User>': undefined method 'checked_at' for User:Class (NoMethodError)

A: 
scope :foo, :where => {:updated_at.gt => self.checked_at}

For example, this will work:

scope :foo, where(:start_date.lte=>Date.today.midnight)
Jesse Wolgamott
That doesn't work. `undefined method `checked_at' for User:Class (NoMethodError)`. The 2nd statement will work, since you are passing in an object. I need to compare two fields that is part of the same document/model.
Jey Balachandran
Need you to post your user class -- just the mongoid include and the definition for checked_at and your scope
Jesse Wolgamott
I edited the original question with the User class. Thanks for your time thus far Jesse.
Jey Balachandran
A: 

As far as I know, mongodb doesn't support queries against dynamic values. But you could use a javascript function:

scope :unresolved, :where => 'this.updated_at >= this.checked_at'

To speed this up you could add an attribute like "is_unresolved" which will be set to true on update when this condition is matched ( and index that ).

Baju
Awesome, this works great. Also thanks for the performance suggestion.
Jey Balachandran
A: 

Not sure if you'll like this method, it's not the best, but it should work.

class User
  include Mongoid::Document
  include Mongoid::Paranoia
  include Mongoid::Timestamps

  field :checked_at, :type => Time

  scope :unresolved, lambda{ |user| where(:updated_at.gt => user.checked_at) }
end

You call it with User.unresolved(my_user_object) It seems now after rereading your post that this probably won't do what you want. If this is true, then you will probably need to use MapReduce or possibly Baju's method (have not tested it)

Preston Marshall