Reputation: 1085
I have models like this
class TestOne
field value
belongs_to test_two ,:class_name => 'TestTwo'
end
class TestTwo
field name
field start_time, :type => DateTime
has_many TestOne
end
I am running a query of range like this
result = TestOne.where(:value => "some_value" , 'test_two.start_time' => (Time.now-1.days..Time.now + 1.days).last
The result set of above query is empty even though there exists several record in TestOne that fulfills the criteria. Can any one suggest what I might be doing wrong.
Upvotes: 1
Views: 2329
Reputation: 434695
A MongoDB query can only access one collection at a time, there are no joins here.
When you say:
'test_two.start_time' => (...)
MongoDB will be looking for a field in test_ones
named test_two
that is a hash (or array of hashes) with a start_time
field inside that hash. You don't have that structure so your query doesn't find anything.
Also, you can query any MongoDB collection for any fields you like and MongoDB won't complain; documents within a collection have no set per-collection structure: any document in any collection can contain any fields with any types. That's why you can use this query without anyone complaining.
You need to do the query in two steps (i.e. do the join by hand):
test_two_ids = TestTwo.where(:start_time => (Time.now-1.days..Time.now + 1.days)).pluck(:id)
result = TestOne.where(:value => "some_value" , :test_two_id.in => test_two_ids).last
There are a couple alternatives that are more work:
db.test_twos.start_time
in the db.test_ones
collection (i.e. precompute the JOIN by denormalizing). This would require you to update the copies every time db.test_twos.start_time
changes and you'd have to periodically sanity check all the copies and fix the broken ones because they will become out of sync.TestTwo
to exist on its own then embed TestTwo
inside TestOne
. This would leave you with a hash field called test_two
inside your db.test_ones
collection and your original query would work. However, you wouldn't be able to access TestTwo
on its own anymore, you'd have to go through TestOne
.Upvotes: 3